Compare commits

..

13 Commits

Author SHA1 Message Date
Sebastiaan Jansssen d94e7cd906 Merge branch 'dev-v7' into master-v7 2018-03-01 15:09:45 +01:00
Sebastiaan Jansssen dde8ba5617 Merge branch 'dev-v7' into master-v7 2018-03-01 14:57:11 +01:00
Sebastiaan Jansssen a633e45b44 Merge branch 'dev-v7' into master-v7 2018-03-01 10:27:57 +01:00
Sebastiaan Jansssen 63b58dcd09 Merge remote-tracking branch 'origin/dev-v7' into master-v7 2018-03-01 07:51:07 +01:00
Sebastiaan Jansssen 76a0c6c39f Merge branch 'dev-v7' into master-v7 2018-02-28 13:28:39 +01:00
Sebastiaan Jansssen 37d2203de1 Merge branch 'dev-v7' into master-v7 2018-02-27 15:45:16 +01:00
Sebastiaan Jansssen 858156bab2 Merge branch 'dev-v7' into master-v7 2018-02-23 22:23:43 +01:00
Sebastiaan Jansssen 2ae96f3810 Merge branch 'dev-v7' into master-v7 2018-02-23 14:23:49 +01:00
Sebastiaan Jansssen a5f689385a Merge branch 'dev-v7' into master-v7 2018-02-19 17:13:35 +01:00
Sebastiaan Jansssen 1607e51270 Merge branch 'dev-v7' into master-v7 2018-02-19 14:21:16 +01:00
Sebastiaan Jansssen 044b43f6e1 Merge branch 'dev-v7' into master-v7 2018-02-19 14:10:09 +01:00
Sebastiaan Jansssen c59a226d56 Merge remote-tracking branch 'origin/dev-v7' into master-v7 2018-02-09 09:51:39 +01:00
Sebastiaan Jansssen 0c25c36af0 Bump version to 7.7.11 2018-02-09 09:46:05 +01:00
23 changed files with 369 additions and 526 deletions
+1 -10
View File
@@ -114,15 +114,6 @@ Some parts of our source code is over 10 years old now. And when we say "old", w
There's two big areas that you should know about:
1. The Umbraco backoffice is a extensible AngularJS app and requires you to run a `gulp dev` command while you're working with it, so changes are copied over to the appropriate directories and you can refresh your browser to view the results of your changes.
You may need to run the following commands to set up gulp properly:
```
npm cache clean
npm install -g bower
npm install -g gulp
npm install -g gulp-cli
npm install
gulp build
```
2. "The rest" is a C# based codebase, with some traces of our WebForms past but mostly ASP.NET MVC based these days. You can make changes, build them in Visual Studio, and hit `F5` to see the result.
To find the general areas of something you're looking to fix or improve, have a look at the following two parts of the API documentation.
@@ -180,4 +171,4 @@ Did something not work as expected? Try leaving a note in the ["Contributing to
## Credits
This contribution guide borrows heavily from the excellent work on [the Atom contribution guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). A big [#h5yr](http://h5yr.com/) to them!
This contribution guide borrows heavily from the excellent work on [the Atom contribution guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). A big [#h5yr](http://h5yr.com/) to them!
@@ -8,7 +8,6 @@ function Get-UmbracoBuildEnv
# store tools in the module's directory
# and cache them for two days
$path = "$PSScriptRoot\temp"
$src = "$PSScriptRoot\..\..\..\src"
$cache = 2
if (-not (test-path $path))
@@ -38,7 +37,7 @@ function Get-UmbracoBuildEnv
if (-not (test-path $sevenZip))
{
Write-Host "Download 7-Zip..."
&$nuget install 7-Zip.CommandLine -configFile "$src\NuGet.config" -OutputDirectory $path -Verbosity quiet
&$nuget install 7-Zip.CommandLine -OutputDirectory $path -Verbosity quiet
$dir = ls "$path\7-Zip.CommandLine.*" | sort -property Name -descending | select -first 1
$file = ls -path "$dir" -name 7za.exe -recurse
$file = ls -path "$dir" -name 7za.exe -recurse | select -first 1 #A select is because there is tools\7za.exe & tools\x64\7za.exe
@@ -55,7 +54,7 @@ function Get-UmbracoBuildEnv
if (-not (test-path $vswhere))
{
Write-Host "Download VsWhere..."
&$nuget install vswhere -configFile "$src\NuGet.config" -OutputDirectory $path -Verbosity quiet
&$nuget install vswhere -OutputDirectory $path -Verbosity quiet
$dir = ls "$path\vswhere.*" | sort -property Name -descending | select -first 1
$file = ls -path "$dir" -name vswhere.exe -recurse
mv "$dir\$file" $vswhere
@@ -71,7 +70,7 @@ function Get-UmbracoBuildEnv
if (-not (test-path $semver))
{
Write-Host "Download Semver..."
&$nuget install semver -configFile "$src\NuGet.config" -OutputDirectory $path -Verbosity quiet
&$nuget install semver -OutputDirectory $path -Verbosity quiet
$dir = ls "$path\semver.*" | sort -property Name -descending | select -first 1
$file = "$dir\lib\net452\Semver.dll"
if (-not (test-path $file))
@@ -445,7 +445,7 @@ function Restore-NuGet
Write-Host ">> Restore NuGet"
Write-Host "Logging to $tmp\nuget.restore.log"
&$uenv.NuGet restore "$src\Umbraco.sln" -configfile "$src\NuGet.config" > "$tmp\nuget.restore.log"
&$uenv.NuGet restore "$src\Umbraco.sln" > "$tmp\nuget.restore.log"
}
#
@@ -2,7 +2,6 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using Umbraco.Core.Configuration;
@@ -27,7 +26,6 @@ namespace Umbraco.Core.IO
private ShadowWrapper _xsltFileSystem;
private ShadowWrapper _masterPagesFileSystem;
private ShadowWrapper _mvcViewsFileSystem;
private ShadowWrapper _javaScriptLibraryFileSystem;
#region Singleton & Constructor
@@ -115,7 +113,6 @@ namespace Umbraco.Core.IO
var xsltFileSystem = new PhysicalFileSystem(SystemDirectories.Xslt);
var masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages);
var mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews);
var javaScriptLibraryFileSystem = new PhysicalFileSystem(Path.Combine(SystemDirectories.Umbraco, "lib"));
_macroPartialFileSystem = new ShadowWrapper(macroPartialFileSystem, "Views/MacroPartials", ScopeProvider);
_partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", ScopeProvider);
@@ -126,7 +123,6 @@ namespace Umbraco.Core.IO
_xsltFileSystem = new ShadowWrapper(xsltFileSystem, "xslt", ScopeProvider);
_masterPagesFileSystem = new ShadowWrapper(masterPagesFileSystem, "masterpages", ScopeProvider);
_mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", ScopeProvider);
_javaScriptLibraryFileSystem = new ShadowWrapper(javaScriptLibraryFileSystem, "Lib", ScopeProvider);
// filesystems obtained from GetFileSystemProvider are already wrapped and do not need to be wrapped again
MediaFileSystem = GetFileSystemProvider<MediaFileSystem>();
@@ -147,7 +143,6 @@ namespace Umbraco.Core.IO
public IFileSystem2 XsltFileSystem { get { return _xsltFileSystem; } }
public IFileSystem2 MasterPagesFileSystem { get { return _mvcViewsFileSystem; } }
public IFileSystem2 MvcViewsFileSystem { get { return _mvcViewsFileSystem; } }
internal IFileSystem2 JavaScriptLibraryFileSystem { get { return _javaScriptLibraryFileSystem; } }
public MediaFileSystem MediaFileSystem { get; private set; }
#endregion
+5 -14
View File
@@ -3,7 +3,6 @@ using System.IO;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
namespace Umbraco.Core
{
@@ -143,18 +142,10 @@ namespace Umbraco.Core
/// <returns></returns>
internal static bool IsClientSideRequest(this Uri url)
{
try
{
var ext = Path.GetExtension(url.LocalPath);
if (ext.IsNullOrWhiteSpace()) return false;
var toInclude = new[] {".aspx", ".ashx", ".asmx", ".axd", ".svc"};
return toInclude.Any(ext.InvariantEquals) == false;
}
catch (ArgumentException ex)
{
LogHelper.Error(typeof(UriExtensions), "Failed to determine if request was client side", ex);
return false;
}
var ext = Path.GetExtension(url.LocalPath);
if (ext.IsNullOrWhiteSpace()) return false;
var toInclude = new[] { ".aspx", ".ashx", ".asmx", ".axd", ".svc" };
return toInclude.Any(ext.InvariantEquals) == false;
}
/// <summary>
@@ -320,4 +311,4 @@ namespace Umbraco.Core
return new Uri(uri.GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped));
}
}
}
}
+40 -46
View File
@@ -93,59 +93,53 @@ namespace Umbraco.Tests.Routing
var result = uri.IsClientSideRequest();
Assert.AreEqual(assert, result);
}
[Test]
public void Is_Client_Side_Request_InvalidPath_ReturnFalse()
{
//This url is invalid. Default to false when the extension cannot be determined
var uri = new Uri("http://test.com/installing-modules+foobar+\"yipee\"");
var result = uri.IsClientSideRequest();
Assert.AreEqual(false, result);
}
//NOTE: This test shows how we can test most of the HttpModule, it however is testing a method that no longer exists and is testing too much,
// we need to write unit tests for each of the components: NiceUrlProvider, all of the Lookup classes, etc...
// to ensure that each one is individually tested.
//[TestCase("/", 1046)]
//[TestCase("/home.aspx", 1046)]
//[TestCase("/home/sub1.aspx", 1173)]
//[TestCase("/home.aspx?altTemplate=blah", 1046)]
//public void Process_Front_End_Document_Request_Match_Node(string url, int nodeId)
//{
// var httpContextFactory = new FakeHttpContextFactory(url);
// var httpContext = httpContextFactory.HttpContext;
// var umbracoContext = new UmbracoContext(httpContext, ApplicationContext.Current, new NullRoutesCache());
// var contentStore = new ContentStore(umbracoContext);
// var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
// umbracoContext.RoutingContext = new RoutingContext(
// new IPublishedContentLookup[] {new LookupByNiceUrl()},
// new DefaultLastChanceLookup(),
// contentStore,
// niceUrls);
// StateHelper.HttpContext = httpContext;
// //because of so much dependency on the db, we need to create som stuff here, i originally abstracted out stuff but
// //was turning out to be quite a deep hole because ultimately we'd have to abstract the old 'Domain' and 'Language' classes
// Domain.MakeNew("Test.com", 1000, Language.GetByCultureCode("en-US").id);
//NOTE: This test shows how we can test most of the HttpModule, it however is testing a method that no longer exists and is testing too much,
// we need to write unit tests for each of the components: NiceUrlProvider, all of the Lookup classes, etc...
// to ensure that each one is individually tested.
// //need to create a template with id 1045
// var template = Template.MakeNew("test", new User(0));
//[TestCase("/", 1046)]
//[TestCase("/home.aspx", 1046)]
//[TestCase("/home/sub1.aspx", 1173)]
//[TestCase("/home.aspx?altTemplate=blah", 1046)]
//public void Process_Front_End_Document_Request_Match_Node(string url, int nodeId)
//{
// var httpContextFactory = new FakeHttpContextFactory(url);
// var httpContext = httpContextFactory.HttpContext;
// var umbracoContext = new UmbracoContext(httpContext, ApplicationContext.Current, new NullRoutesCache());
// var contentStore = new ContentStore(umbracoContext);
// var niceUrls = new NiceUrlProvider(contentStore, umbracoContext);
// umbracoContext.RoutingContext = new RoutingContext(
// new IPublishedContentLookup[] {new LookupByNiceUrl()},
// new DefaultLastChanceLookup(),
// contentStore,
// niceUrls);
// SetupUmbracoContextForTest(umbracoContext, template);
// StateHelper.HttpContext = httpContext;
// _module.AssignDocumentRequest(httpContext, umbracoContext, httpContext.Request.Url);
// //because of so much dependency on the db, we need to create som stuff here, i originally abstracted out stuff but
// //was turning out to be quite a deep hole because ultimately we'd have to abstract the old 'Domain' and 'Language' classes
// Domain.MakeNew("Test.com", 1000, Language.GetByCultureCode("en-US").id);
// Assert.IsNotNull(umbracoContext.PublishedContentRequest);
// Assert.IsNotNull(umbracoContext.PublishedContentRequest.XmlNode);
// Assert.IsFalse(umbracoContext.PublishedContentRequest.IsRedirect);
// Assert.IsFalse(umbracoContext.PublishedContentRequest.Is404);
// Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentCulture);
// Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentUICulture);
// Assert.AreEqual(nodeId, umbracoContext.PublishedContentRequest.NodeId);
// //need to create a template with id 1045
// var template = Template.MakeNew("test", new User(0));
//}
// SetupUmbracoContextForTest(umbracoContext, template);
}
}
// _module.AssignDocumentRequest(httpContext, umbracoContext, httpContext.Request.Url);
// Assert.IsNotNull(umbracoContext.PublishedContentRequest);
// Assert.IsNotNull(umbracoContext.PublishedContentRequest.XmlNode);
// Assert.IsFalse(umbracoContext.PublishedContentRequest.IsRedirect);
// Assert.IsFalse(umbracoContext.PublishedContentRequest.Is404);
// Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentCulture);
// Assert.AreEqual(umbracoContext.PublishedContentRequest.Culture, Thread.CurrentThread.CurrentUICulture);
// Assert.AreEqual(nodeId, umbracoContext.PublishedContentRequest.NodeId);
//}
}
}
+1 -6
View File
@@ -42,12 +42,7 @@
"codemirror"
],
"sources": {
"moment": [
"bower_components/moment/min/moment.min.js",
"bower_components/moment/min/moment-with-locales.js",
"bower_components/moment/min/moment-with-locales.min.js",
"bower_components/moment/locale/*.js"
],
"moment": "bower_components/moment/min/moment-with-locales.js",
"underscore": [
"bower_components/underscore/underscore-min.js",
"bower_components/underscore/underscore-min.map"
@@ -50,7 +50,7 @@
scope.openDocumentType = function (documentType) {
var url = "/settings/documenttypes/edit/" + documentType.id;
$location.url(url);
$location.path(url);
};
scope.updateTemplate = function (templateAlias) {
@@ -10,12 +10,12 @@ function noDirtyCheck() {
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
var alwaysFalse = {
get: function () { return false; },
set: function () { }
};
Object.defineProperty(ctrl, '$pristine', alwaysFalse);
Object.defineProperty(ctrl, '$dirty', alwaysFalse);
elm.focus(function () {
scope.$watch(function() {
ctrl.$pristine = false;
});
});
}
};
@@ -1,40 +0,0 @@
(function () {
'use strict';
function javascriptLibraryService($q, $http, umbRequestHelper) {
var existingLocales = [];
function getSupportedLocalesForMoment() {
var deferred = $q.defer();
if (existingLocales.length === 0) {
umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"backOfficeAssetsApiBaseUrl",
"GetSupportedMomentLocales")),
'Failed to get cultures').then(function(locales) {
existingLocales = locales;
deferred.resolve(existingLocales);
});
} else {
deferred.resolve(existingLocales);
}
return deferred.promise;
}
var service = {
getSupportedLocalesForMoment: getSupportedLocalesForMoment
};
return service;
}
angular.module('umbraco.services').factory('javascriptLibraryService', javascriptLibraryService);
})();
@@ -1,324 +1,285 @@
angular.module('umbraco.services')
.factory('userService', function ($rootScope, eventsService, $q, $location, $log, securityRetryQueue, authResource, assetsService, dialogService, $timeout, angularHelper, $http, javascriptLibraryService) {
.factory('userService', function ($rootScope, eventsService, $q, $location, $log, securityRetryQueue, authResource, dialogService, $timeout, angularHelper, $http) {
var currentUser = null;
var lastUserId = null;
var loginDialog = null;
var currentUser = null;
var lastUserId = null;
var loginDialog = null;
//this tracks the last date/time that the user's remainingAuthSeconds was updated from the server
// this is used so that we know when to go and get the user's remaining seconds directly.
var lastServerTimeoutSet = null;
//this tracks the last date/time that the user's remainingAuthSeconds was updated from the server
// this is used so that we know when to go and get the user's remaining seconds directly.
var lastServerTimeoutSet = null;
function openLoginDialog(isTimedOut) {
if (!loginDialog) {
loginDialog = dialogService.open({
function openLoginDialog(isTimedOut) {
if (!loginDialog) {
loginDialog = dialogService.open({
//very special flag which means that global events cannot close this dialog
manualClose: true,
//very special flag which means that global events cannot close this dialog
manualClose: true,
template: 'views/common/dialogs/login.html',
modalClass: "login-overlay",
animation: "slide",
show: true,
callback: onLoginDialogClose,
dialogData: {
isTimedOut: isTimedOut
}
template: 'views/common/dialogs/login.html',
modalClass: "login-overlay",
animation: "slide",
show: true,
callback: onLoginDialogClose,
dialogData: {
isTimedOut: isTimedOut
}
});
}
}
function onLoginDialogClose(success) {
loginDialog = null;
if (success) {
securityRetryQueue.retryAll(currentUser.name);
}
else {
securityRetryQueue.cancelAll();
$location.path('/');
}
}
/**
This methods will set the current user when it is resolved and
will then start the counter to count in-memory how many seconds they have
remaining on the auth session
*/
function setCurrentUser(usr) {
if (!usr.remainingAuthSeconds) {
throw "The user object is invalid, the remainingAuthSeconds is required.";
}
currentUser = usr;
lastServerTimeoutSet = new Date();
//start the timer
countdownUserTimeout();
}
/**
Method to count down the current user's timeout seconds,
this will continually count down their current remaining seconds every 5 seconds until
there are no more seconds remaining.
*/
function countdownUserTimeout() {
$timeout(function () {
if (currentUser) {
//countdown by 5 seconds since that is how long our timer is for.
currentUser.remainingAuthSeconds -= 5;
//if there are more than 30 remaining seconds, recurse!
if (currentUser.remainingAuthSeconds > 30) {
//we need to check when the last time the timeout was set from the server, if
// it has been more than 30 seconds then we'll manually go and retrieve it from the
// server - this helps to keep our local countdown in check with the true timeout.
if (lastServerTimeoutSet != null) {
var now = new Date();
var seconds = (now.getTime() - lastServerTimeoutSet.getTime()) / 1000;
if (seconds > 30) {
//first we'll set the lastServerTimeoutSet to null - this is so we don't get back in to this loop while we
// wait for a response from the server otherwise we'll be making double/triple/etc... calls while we wait.
lastServerTimeoutSet = null;
//now go get it from the server
//NOTE: the safeApply because our timeout is set to not run digests (performance reasons)
angularHelper.safeApply($rootScope, function () {
authResource.getRemainingTimeoutSeconds().then(function (result) {
setUserTimeoutInternal(result);
});
});
}
}
}
function onLoginDialogClose(success) {
loginDialog = null;
//recurse the countdown!
countdownUserTimeout();
}
else {
if (success) {
securityRetryQueue.retryAll(currentUser.name);
//we are either timed out or very close to timing out so we need to show the login dialog.
if (Umbraco.Sys.ServerVariables.umbracoSettings.keepUserLoggedIn !== true) {
//NOTE: the safeApply because our timeout is set to not run digests (performance reasons)
angularHelper.safeApply($rootScope, function () {
try {
//NOTE: We are calling this again so that the server can create a log that the timeout has expired, we
// don't actually care about this result.
authResource.getRemainingTimeoutSeconds();
}
finally {
userAuthExpired();
}
});
}
else {
securityRetryQueue.cancelAll();
$location.path('/');
}
}
//we've got less than 30 seconds remaining so let's check the server
/**
This methods will set the current user when it is resolved and
will then start the counter to count in-memory how many seconds they have
remaining on the auth session
*/
function setCurrentUser(usr) {
if (!usr.remainingAuthSeconds) {
throw "The user object is invalid, the remainingAuthSeconds is required.";
}
currentUser = usr;
lastServerTimeoutSet = new Date();
//start the timer
countdownUserTimeout();
}
if (lastServerTimeoutSet != null) {
//first we'll set the lastServerTimeoutSet to null - this is so we don't get back in to this loop while we
// wait for a response from the server otherwise we'll be making double/triple/etc... calls while we wait.
lastServerTimeoutSet = null;
/**
Method to count down the current user's timeout seconds,
this will continually count down their current remaining seconds every 5 seconds until
there are no more seconds remaining.
*/
function countdownUserTimeout() {
$timeout(function () {
if (currentUser) {
//countdown by 5 seconds since that is how long our timer is for.
currentUser.remainingAuthSeconds -= 5;
//if there are more than 30 remaining seconds, recurse!
if (currentUser.remainingAuthSeconds > 30) {
//we need to check when the last time the timeout was set from the server, if
// it has been more than 30 seconds then we'll manually go and retrieve it from the
// server - this helps to keep our local countdown in check with the true timeout.
if (lastServerTimeoutSet != null) {
var now = new Date();
var seconds = (now.getTime() - lastServerTimeoutSet.getTime()) / 1000;
if (seconds > 30) {
//first we'll set the lastServerTimeoutSet to null - this is so we don't get back in to this loop while we
// wait for a response from the server otherwise we'll be making double/triple/etc... calls while we wait.
lastServerTimeoutSet = null;
//now go get it from the server
//NOTE: the safeApply because our timeout is set to not run digests (performance reasons)
angularHelper.safeApply($rootScope, function () {
authResource.getRemainingTimeoutSeconds().then(function (result) {
setUserTimeoutInternal(result);
});
});
}
}
//recurse the countdown!
countdownUserTimeout();
}
else {
//we are either timed out or very close to timing out so we need to show the login dialog.
if (Umbraco.Sys.ServerVariables.umbracoSettings.keepUserLoggedIn !== true) {
//NOTE: the safeApply because our timeout is set to not run digests (performance reasons)
angularHelper.safeApply($rootScope, function () {
try {
//NOTE: We are calling this again so that the server can create a log that the timeout has expired, we
// don't actually care about this result.
authResource.getRemainingTimeoutSeconds();
}
finally {
userAuthExpired();
}
});
}
else {
//we've got less than 30 seconds remaining so let's check the server
if (lastServerTimeoutSet != null) {
//first we'll set the lastServerTimeoutSet to null - this is so we don't get back in to this loop while we
// wait for a response from the server otherwise we'll be making double/triple/etc... calls while we wait.
lastServerTimeoutSet = null;
//now go get it from the server
//NOTE: the safeApply because our timeout is set to not run digests (performance reasons)
angularHelper.safeApply($rootScope, function () {
authResource.getRemainingTimeoutSeconds().then(function (result) {
setUserTimeoutInternal(result);
});
});
}
//recurse the countdown!
countdownUserTimeout();
}
}
}
}, 5000, //every 5 seconds
false); //false = do NOT execute a digest for every iteration
}
/** Called to update the current user's timeout */
function setUserTimeoutInternal(newTimeout) {
var asNumber = parseFloat(newTimeout);
if (!isNaN(asNumber) && currentUser && angular.isNumber(asNumber)) {
currentUser.remainingAuthSeconds = newTimeout;
lastServerTimeoutSet = new Date();
}
}
/** resets all user data, broadcasts the notAuthenticated event and shows the login dialog */
function userAuthExpired(isLogout) {
//store the last user id and clear the user
if (currentUser && currentUser.id !== undefined) {
lastUserId = currentUser.id;
}
if (currentUser) {
currentUser.remainingAuthSeconds = 0;
}
lastServerTimeoutSet = null;
currentUser = null;
//broadcast a global event that the user is no longer logged in
eventsService.emit("app.notAuthenticated");
openLoginDialog(isLogout === undefined ? true : !isLogout);
}
// Register a handler for when an item is added to the retry queue
securityRetryQueue.onItemAddedCallbacks.push(function (retryItem) {
if (securityRetryQueue.hasMore()) {
userAuthExpired();
}
});
return {
/** Internal method to display the login dialog */
_showLoginDialog: function () {
openLoginDialog();
},
/** Returns a promise, sends a request to the server to check if the current cookie is authorized */
isAuthenticated: function () {
//if we've got a current user then just return true
if (currentUser) {
var deferred = $q.defer();
deferred.resolve(true);
return deferred.promise;
}
return authResource.isAuthenticated();
},
/** Returns a promise, sends a request to the server to validate the credentials */
authenticate: function (login, password) {
return authResource.performLogin(login, password)
.then(this.setAuthenticationSuccessful);
},
setAuthenticationSuccessful: function (data) {
//when it's successful, return the user data
setCurrentUser(data);
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "credentials" };
//broadcast a global event
eventsService.emit("app.authenticated", result);
return result;
},
/** Logs the user out
*/
logout: function () {
return authResource.performLogout()
.then(function (data) {
userAuthExpired();
//done!
return null;
});
},
/** Refreshes the current user data with the data stored for the user on the server and returns it */
refreshCurrentUser: function () {
var deferred = $q.defer();
authResource.getCurrentUser()
.then(function (data) {
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "implicit" };
setCurrentUser(data);
deferred.resolve(currentUser);
}, function () {
//it failed, so they are not logged in
deferred.reject();
});
return deferred.promise;
},
/** Returns the current user object in a promise */
getCurrentUser: function (args) {
var deferred = $q.defer();
if (!currentUser) {
authResource.getCurrentUser()
.then(function (data) {
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "implicit" };
if (args && args.broadcastEvent) {
//broadcast a global event, will inform listening controllers to load in the user specific data
eventsService.emit("app.authenticated", result);
}
setCurrentUser(data);
deferred.resolve(currentUser);
}, function () {
//it failed, so they are not logged in
deferred.reject();
});
}
else {
deferred.resolve(currentUser);
}
return deferred.promise;
},
/** Loads the Moment.js Locale for the current user. */
loadMomentLocaleForCurrentUser: function () {
var deferred = $q.defer();
function loadLocales(currentUser, supportedLocales) {
var locale = currentUser.locale.toLowerCase();
if (locale !== 'en-us') {
var localeUrls = [];
if (supportedLocales.indexOf(locale + '.js') > -1) {
localeUrls.push('lib/moment/' + locale + '.js');
}
if (locale.indexOf('-') > -1) {
var majorLocale = locale.split('-')[0] + '.js';
if (supportedLocales.indexOf(majorLocale) > -1) {
localeUrls.push('lib/moment/' + majorLocale);
}
}
assetsService.load(localeUrls).then(function () {
deferred.resolve(localeUrls);
});
} else {
deferred.resolve(['']);
}
}
var promises = {
currentUser: this.getCurrentUser(),
supportedLocales: javascriptLibraryService.getSupportedLocalesForMoment()
}
$q.all(promises).then((values) => {
loadLocales(values.currentUser, values.supportedLocales);
//now go get it from the server
//NOTE: the safeApply because our timeout is set to not run digests (performance reasons)
angularHelper.safeApply($rootScope, function () {
authResource.getRemainingTimeoutSeconds().then(function (result) {
setUserTimeoutInternal(result);
});
});
return deferred.promise;
}
},
//recurse the countdown!
countdownUserTimeout();
/** Called whenever a server request is made that contains a x-umb-user-seconds response header for which we can update the user's remaining timeout seconds */
setUserTimeout: function (newTimeout) {
setUserTimeoutInternal(newTimeout);
}
};
}
}
}, 5000, //every 5 seconds
false); //false = do NOT execute a digest for every iteration
}
/** Called to update the current user's timeout */
function setUserTimeoutInternal(newTimeout) {
var asNumber = parseFloat(newTimeout);
if (!isNaN(asNumber) && currentUser && angular.isNumber(asNumber)) {
currentUser.remainingAuthSeconds = newTimeout;
lastServerTimeoutSet = new Date();
}
}
/** resets all user data, broadcasts the notAuthenticated event and shows the login dialog */
function userAuthExpired(isLogout) {
//store the last user id and clear the user
if (currentUser && currentUser.id !== undefined) {
lastUserId = currentUser.id;
}
if (currentUser) {
currentUser.remainingAuthSeconds = 0;
}
lastServerTimeoutSet = null;
currentUser = null;
//broadcast a global event that the user is no longer logged in
eventsService.emit("app.notAuthenticated");
openLoginDialog(isLogout === undefined ? true : !isLogout);
}
// Register a handler for when an item is added to the retry queue
securityRetryQueue.onItemAddedCallbacks.push(function (retryItem) {
if (securityRetryQueue.hasMore()) {
userAuthExpired();
}
});
return {
/** Internal method to display the login dialog */
_showLoginDialog: function () {
openLoginDialog();
},
/** Returns a promise, sends a request to the server to check if the current cookie is authorized */
isAuthenticated: function () {
//if we've got a current user then just return true
if (currentUser) {
var deferred = $q.defer();
deferred.resolve(true);
return deferred.promise;
}
return authResource.isAuthenticated();
},
/** Returns a promise, sends a request to the server to validate the credentials */
authenticate: function (login, password) {
return authResource.performLogin(login, password)
.then(this.setAuthenticationSuccessful);
},
setAuthenticationSuccessful: function (data) {
//when it's successful, return the user data
setCurrentUser(data);
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "credentials" };
//broadcast a global event
eventsService.emit("app.authenticated", result);
return result;
},
/** Logs the user out
*/
logout: function () {
return authResource.performLogout()
.then(function (data) {
userAuthExpired();
//done!
return null;
});
},
/** Refreshes the current user data with the data stored for the user on the server and returns it */
refreshCurrentUser: function() {
var deferred = $q.defer();
authResource.getCurrentUser()
.then(function (data) {
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "implicit" };
setCurrentUser(data);
deferred.resolve(currentUser);
}, function () {
//it failed, so they are not logged in
deferred.reject();
});
return deferred.promise;
},
/** Returns the current user object in a promise */
getCurrentUser: function (args) {
var deferred = $q.defer();
if (!currentUser) {
authResource.getCurrentUser()
.then(function (data) {
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "implicit" };
if (args && args.broadcastEvent) {
//broadcast a global event, will inform listening controllers to load in the user specific data
eventsService.emit("app.authenticated", result);
}
setCurrentUser(data);
deferred.resolve(currentUser);
}, function () {
//it failed, so they are not logged in
deferred.reject();
});
}
else {
deferred.resolve(currentUser);
}
return deferred.promise;
},
/** Called whenever a server request is made that contains a x-umb-user-seconds response header for which we can update the user's remaining timeout seconds */
setUserTimeout: function (newTimeout) {
setUserTimeoutInternal(newTimeout);
}
};
});
+15 -18
View File
@@ -18,26 +18,23 @@ app.run(['userService', '$log', '$rootScope', '$location', 'queryStrings', 'navi
eventsService.on("app.authenticated", function(evt, data) {
assetsService._loadInitAssets().then(function() {
// 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);
//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);
});
});
});
@@ -15,7 +15,7 @@ function ColorPickerController($scope) {
$scope.toggleItem = function (color) {
var currentColor = ($scope.model.value && $scope.model.value.hasOwnProperty("value"))
var currentColor = $scope.model.value.hasOwnProperty("value")
? $scope.model.value.value
: $scope.model.value;
@@ -130,9 +130,6 @@ function fileUploadController($scope, $element, $compile, imageHelper, fileManag
// in the description of this controller, it states that this value isn't actually used for persistence,
// but we need to set it so that the editor and the server can detect that it's been changed, and it is used for validation.
$scope.model.value = { selectedFiles: newVal.trimEnd(",") };
//need to explicity setDirty here as file upload field can't track dirty & we can't use the fileCount (hidden field/model)
$scope.propertyForm.$setDirty();
});
});
@@ -157,24 +154,26 @@ angular.module("umbraco")
.controller('Umbraco.PropertyEditors.FileUploadController', fileUploadController)
.run(function(mediaHelper, umbRequestHelper, assetsService){
if (mediaHelper && mediaHelper.registerFileResolver) {
//NOTE: The 'entity' can be either a normal media entity or an "entity" returned from the entityResource
// they contain different data structures so if we need to query against it we need to be aware of this.
mediaHelper.registerFileResolver("Umbraco.UploadField", function(property, entity, thumbnail){
if (thumbnail) {
if (mediaHelper.detectIfImageByExtension(property.value)) {
//get default big thumbnail from image processor
var thumbnailUrl = property.value + "?rnd=" + moment(entity.updateDate).format("YYYYMMDDHHmmss") + "&width=500&animationprocessmode=first";
return thumbnailUrl;
}
else {
return null;
}
assetsService.load(["lib/moment/moment-with-locales.js"]).then(
function () {
//NOTE: The 'entity' can be either a normal media entity or an "entity" returned from the entityResource
// they contain different data structures so if we need to query against it we need to be aware of this.
mediaHelper.registerFileResolver("Umbraco.UploadField", function(property, entity, thumbnail){
if (thumbnail) {
if (mediaHelper.detectIfImageByExtension(property.value)) {
//get default big thumbnail from image processor
var thumbnailUrl = property.value + "?rnd=" + moment(entity.updateDate).format("YYYYMMDDHHmmss") + "&width=500&animationprocessmode=first";
return thumbnailUrl;
}
else {
return null;
}
}
else {
return property.value;
}
});
}
else {
return property.value;
}
});
);
}
});
@@ -31,6 +31,6 @@
</ul>
</div>
<input type="hidden" name="fileCount" ng-model="files.length" val-property-validator="validateMandatory" no-dirty-check />
<input type="hidden" name="fileCount" ng-model="files.length" val-property-validator="validateMandatory"/>
</div>
@@ -99,4 +99,4 @@ module.exports = function (config) {
'karma-phantomjs-launcher'
]
});
};
};
@@ -13,10 +13,8 @@
url += "&mode=crop";
}
}
var altText = Model.value.altText ?? Model.value.caption ?? string.Empty;
<img src="@url" alt="@altText">
<img src="@url" alt="@Model.value.caption">
if (Model.value.caption != null)
{
@@ -38,7 +38,7 @@
<key alias="update">Bijwerken</key>
</area>
<area alias="assignDomain">
<key alias="permissionDenied">Toegang geweigerd.</key>
<key alias="permissionDenied">Permission denied.</key>
<key alias="addNew">Nieuw domein toevoegen</key>
<key alias="remove">verwijderen</key>
<key alias="invalidNode">Ongeldige node.</key>
@@ -1379,10 +1379,10 @@ Om een vertalingstaak te sluiten, ga aub naar het detailoverzicht en klik op de
<key alias="httpsCheckEnableHttpsDescription">Zet in de appSettings van de web.config de umbracoSSL instelling op 'true'.</key>
<key alias="httpsCheckEnableHttpsSuccess">De appSetting 'umbracoUseSSL' is nu ingesteld op 'true', cookies zullen als 'secure' worden aangemerkt.</key>
<key alias="rectifyButton">Herstellen</key>
<key alias="cannotRectifyShouldNotEqual">Kan een controle met vergelijkingstype 'ShouldNotEqual' niet herstellen.</key>
<key alias="cannotRectifyShouldEqualWithValue">Kan een controle met vergelijkingstype 'ShouldNotEqual' en gedefinieerde waarde niet herstellen.</key>
<key alias="valueToRectifyNotProvided">Waarde om te herstellen niet gedefinieerd.</key>
<key alias="rectifyButton">Fix</key>
<key alias="cannotRectifyShouldNotEqual">Cannot fix a check with a value comparison type of 'ShouldNotEqual'.</key>
<key alias="cannotRectifyShouldEqualWithValue">Cannot fix a check with a value comparison type of 'ShouldEqual' with a provided value.</key>
<key alias="valueToRectifyNotProvided">Value to fix check not provided.</key>
<key alias="compilationDebugCheckSuccessMessage">Debug compiliate mode staat uit.</key>
<key alias="compilationDebugCheckErrorMessage">Debug compiliate mode staat momenteel aan. Wij raden aan deze instelling uit te zetten voor livegang.</key>
@@ -1,28 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using Umbraco.Core.IO;
using Umbraco.Web.Mvc;
namespace Umbraco.Web.Editors
{
[PluginController("UmbracoApi")]
public class BackOfficeAssetsController : UmbracoAuthorizedJsonController
{
[HttpGet]
public IEnumerable<string> GetSupportedMomentLocales()
{
var momentLocaleFolder = "moment";
var fileSystem = FileSystemProviderManager.Current.JavaScriptLibraryFileSystem;
var cultures = fileSystem.GetFiles(momentLocaleFolder, "*.js").ToList();
for (var i = 0; i < cultures.Count(); i++)
{
cultures[i] = cultures[i]
.Substring(cultures[i].IndexOf(momentLocaleFolder) + momentLocaleFolder.Length + 1);
}
return cultures;
}
}
}
@@ -268,10 +268,6 @@ namespace Umbraco.Web.Editors
{
"helpApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<HelpController>(
controller => controller.GetContextHelpForPage("","",""))
},
{
"backOfficeAssetsApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<BackOfficeAssetsController>(
controller => controller.GetSupportedMomentLocales())
}
}
},
+1 -5
View File
@@ -63,10 +63,6 @@ namespace Umbraco.Web.Scheduling
{
using (var wc = new HttpClient())
{
if (Uri.TryCreate(_appContext.UmbracoApplicationUrl, UriKind.Absolute, out var baseUri))
{
wc.BaseAddress = baseUri;
}
var request = new HttpRequestMessage(HttpMethod.Get, url);
//TODO: pass custom the authorization header, currently these aren't really secured!
@@ -126,4 +122,4 @@ namespace Umbraco.Web.Scheduling
get { return true; }
}
}
}
}
@@ -3,7 +3,7 @@
'lib/angular/1.1.5/angular.min.js',
'lib/underscore/underscore-min.js',
'lib/moment/moment.min.js',
'lib/moment/moment-with-locales.js',
'lib/jquery-ui/jquery-ui.min.js',
'lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js',
-1
View File
@@ -316,7 +316,6 @@
<Compile Include="Cache\TemplateCacheRefresher.cs" />
<Compile Include="Cache\UnpublishedPageCacheRefresher.cs" />
<Compile Include="Cache\UserCacheRefresher.cs" />
<Compile Include="Editors\BackOfficeAssetsController .cs" />
<Compile Include="Features\DisabledFeatures.cs" />
<Compile Include="Editors\BackOfficeNotificationsController.cs" />
<Compile Include="Editors\BackOfficeServerVariables.cs" />