Compare commits
26 Commits
release-7.9.2
...
pr/2507
| Author | SHA1 | Date | |
|---|---|---|---|
| b0230a1586 | |||
| 57426ae895 | |||
| 6bafd3a254 | |||
| 564074a2bd | |||
| 617bdb2bd1 | |||
| 2c91f9bf14 | |||
| f146262031 | |||
| ddae0d01e3 | |||
| b9ee85dabc | |||
| 29fa6061a9 | |||
| 8ee61312b6 | |||
| cfd4b8c7bf | |||
| 7ce3b6046c | |||
| 43d98c9682 | |||
| 62e4825a5e | |||
| 81d35c6079 | |||
| 7e15077f96 | |||
| 6543e3c058 | |||
| 7c73c379cf | |||
| 4bc9d96bce | |||
| 45fd54d046 | |||
| 4f062306a6 | |||
| 0beda4b790 | |||
| da0a1c808a | |||
| 08965982fd | |||
| b37197f66a |
+10
-1
@@ -114,6 +114,15 @@ 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.
|
||||
@@ -171,4 +180,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,6 +8,7 @@ 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))
|
||||
@@ -37,7 +38,7 @@ function Get-UmbracoBuildEnv
|
||||
if (-not (test-path $sevenZip))
|
||||
{
|
||||
Write-Host "Download 7-Zip..."
|
||||
&$nuget install 7-Zip.CommandLine -OutputDirectory $path -Verbosity quiet
|
||||
&$nuget install 7-Zip.CommandLine -configFile "$src\NuGet.config" -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
|
||||
@@ -54,7 +55,7 @@ function Get-UmbracoBuildEnv
|
||||
if (-not (test-path $vswhere))
|
||||
{
|
||||
Write-Host "Download VsWhere..."
|
||||
&$nuget install vswhere -OutputDirectory $path -Verbosity quiet
|
||||
&$nuget install vswhere -configFile "$src\NuGet.config" -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
|
||||
@@ -70,7 +71,7 @@ function Get-UmbracoBuildEnv
|
||||
if (-not (test-path $semver))
|
||||
{
|
||||
Write-Host "Download Semver..."
|
||||
&$nuget install semver -OutputDirectory $path -Verbosity quiet
|
||||
&$nuget install semver -configFile "$src\NuGet.config" -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" > "$tmp\nuget.restore.log"
|
||||
&$uenv.NuGet restore "$src\Umbraco.sln" -configfile "$src\NuGet.config" > "$tmp\nuget.restore.log"
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Umbraco.Core.Configuration;
|
||||
@@ -26,6 +27,7 @@ namespace Umbraco.Core.IO
|
||||
private ShadowWrapper _xsltFileSystem;
|
||||
private ShadowWrapper _masterPagesFileSystem;
|
||||
private ShadowWrapper _mvcViewsFileSystem;
|
||||
private ShadowWrapper _javaScriptLibraryFileSystem;
|
||||
|
||||
#region Singleton & Constructor
|
||||
|
||||
@@ -113,6 +115,7 @@ 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);
|
||||
@@ -123,6 +126,7 @@ 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>();
|
||||
@@ -143,6 +147,7 @@ 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
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -142,10 +143,18 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
internal static bool IsClientSideRequest(this Uri url)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -311,4 +320,4 @@ namespace Umbraco.Core
|
||||
return new Uri(uri.GetComponents(UriComponents.AbsoluteUri & ~UriComponents.Port, UriFormat.UriEscaped));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,53 +93,59 @@ 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;
|
||||
|
||||
//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.
|
||||
// //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);
|
||||
|
||||
//[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);
|
||||
// //need to create a template with id 1045
|
||||
// var template = Template.MakeNew("test", new User(0));
|
||||
|
||||
// StateHelper.HttpContext = httpContext;
|
||||
// SetupUmbracoContextForTest(umbracoContext, template);
|
||||
|
||||
// //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);
|
||||
// _module.AssignDocumentRequest(httpContext, umbracoContext, httpContext.Request.Url);
|
||||
|
||||
// //need to create a template with id 1045
|
||||
// var template = Template.MakeNew("test", new User(0));
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,12 @@
|
||||
"codemirror"
|
||||
],
|
||||
"sources": {
|
||||
"moment": "bower_components/moment/min/moment-with-locales.js",
|
||||
"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"
|
||||
],
|
||||
"underscore": [
|
||||
"bower_components/underscore/underscore-min.js",
|
||||
"bower_components/underscore/underscore-min.map"
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@
|
||||
|
||||
scope.openDocumentType = function (documentType) {
|
||||
var url = "/settings/documenttypes/edit/" + documentType.id;
|
||||
$location.path(url);
|
||||
$location.url(url);
|
||||
};
|
||||
|
||||
scope.updateTemplate = function (templateAlias) {
|
||||
|
||||
+6
-6
@@ -10,12 +10,12 @@ function noDirtyCheck() {
|
||||
require: 'ngModel',
|
||||
link: function (scope, elm, attrs, ctrl) {
|
||||
|
||||
elm.focus(function () {
|
||||
scope.$watch(function() {
|
||||
ctrl.$pristine = false;
|
||||
});
|
||||
});
|
||||
|
||||
var alwaysFalse = {
|
||||
get: function () { return false; },
|
||||
set: function () { }
|
||||
};
|
||||
Object.defineProperty(ctrl, '$pristine', alwaysFalse);
|
||||
Object.defineProperty(ctrl, '$dirty', alwaysFalse);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
(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,285 +1,324 @@
|
||||
angular.module('umbraco.services')
|
||||
.factory('userService', function ($rootScope, eventsService, $q, $location, $log, securityRetryQueue, authResource, dialogService, $timeout, angularHelper, $http) {
|
||||
.factory('userService', function ($rootScope, eventsService, $q, $location, $log, securityRetryQueue, authResource, assetsService, dialogService, $timeout, angularHelper, $http, javascriptLibraryService) {
|
||||
|
||||
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
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
});
|
||||
template: 'views/common/dialogs/login.html',
|
||||
modalClass: "login-overlay",
|
||||
animation: "slide",
|
||||
show: true,
|
||||
callback: onLoginDialogClose,
|
||||
dialogData: {
|
||||
isTimedOut: isTimedOut
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//recurse the countdown!
|
||||
countdownUserTimeout();
|
||||
}
|
||||
else {
|
||||
function onLoginDialogClose(success) {
|
||||
loginDialog = null;
|
||||
|
||||
//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();
|
||||
}
|
||||
});
|
||||
if (success) {
|
||||
securityRetryQueue.retryAll(currentUser.name);
|
||||
}
|
||||
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();
|
||||
|
||||
securityRetryQueue.cancelAll();
|
||||
$location.path('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 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;
|
||||
/**
|
||||
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();
|
||||
}
|
||||
return authResource.isAuthenticated();
|
||||
},
|
||||
|
||||
/** Returns a promise, sends a request to the server to validate the credentials */
|
||||
authenticate: function (login, password) {
|
||||
/**
|
||||
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() {
|
||||
|
||||
return authResource.performLogin(login, password)
|
||||
.then(this.setAuthenticationSuccessful);
|
||||
},
|
||||
setAuthenticationSuccessful: function (data) {
|
||||
$timeout(function () {
|
||||
|
||||
//when it's successful, return the user data
|
||||
setCurrentUser(data);
|
||||
if (currentUser) {
|
||||
//countdown by 5 seconds since that is how long our timer is for.
|
||||
currentUser.remainingAuthSeconds -= 5;
|
||||
|
||||
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "credentials" };
|
||||
//if there are more than 30 remaining seconds, recurse!
|
||||
if (currentUser.remainingAuthSeconds > 30) {
|
||||
|
||||
//broadcast a global event
|
||||
eventsService.emit("app.authenticated", result);
|
||||
return result;
|
||||
},
|
||||
//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;
|
||||
|
||||
/** Logs the user out
|
||||
*/
|
||||
logout: function () {
|
||||
if (seconds > 30) {
|
||||
|
||||
return authResource.performLogout()
|
||||
.then(function (data) {
|
||||
userAuthExpired();
|
||||
//done!
|
||||
return 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;
|
||||
|
||||
/** Refreshes the current user data with the data stored for the user on the server and returns it */
|
||||
refreshCurrentUser: function() {
|
||||
var deferred = $q.defer();
|
||||
//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);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
authResource.getCurrentUser()
|
||||
.then(function (data) {
|
||||
//recurse the countdown!
|
||||
countdownUserTimeout();
|
||||
}
|
||||
else {
|
||||
|
||||
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "implicit" };
|
||||
|
||||
setCurrentUser(data);
|
||||
//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
|
||||
|
||||
deferred.resolve(currentUser);
|
||||
}, function () {
|
||||
//it failed, so they are not logged in
|
||||
deferred.reject();
|
||||
});
|
||||
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;
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
//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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** Returns the current user object in a promise */
|
||||
getCurrentUser: function (args) {
|
||||
var deferred = $q.defer();
|
||||
//recurse the countdown!
|
||||
countdownUserTimeout();
|
||||
|
||||
if (!currentUser) {
|
||||
authResource.getCurrentUser()
|
||||
.then(function (data) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 5000, //every 5 seconds
|
||||
false); //false = do NOT execute a digest for every iteration
|
||||
}
|
||||
|
||||
var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "implicit" };
|
||||
/** Called to update the current user's timeout */
|
||||
function setUserTimeoutInternal(newTimeout) {
|
||||
|
||||
if (args && args.broadcastEvent) {
|
||||
//broadcast a global event, will inform listening controllers to load in the user specific data
|
||||
|
||||
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;
|
||||
},
|
||||
|
||||
setCurrentUser(data);
|
||||
/** Logs the user out
|
||||
*/
|
||||
logout: function () {
|
||||
|
||||
deferred.resolve(currentUser);
|
||||
}, function () {
|
||||
//it failed, so they are not logged in
|
||||
deferred.reject();
|
||||
});
|
||||
return authResource.performLogout()
|
||||
.then(function (data) {
|
||||
userAuthExpired();
|
||||
//done!
|
||||
return null;
|
||||
});
|
||||
},
|
||||
|
||||
}
|
||||
else {
|
||||
deferred.resolve(currentUser);
|
||||
}
|
||||
/** Refreshes the current user data with the data stored for the user on the server and returns it */
|
||||
refreshCurrentUser: function () {
|
||||
var deferred = $q.defer();
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
authResource.getCurrentUser()
|
||||
.then(function (data) {
|
||||
|
||||
/** 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);
|
||||
}
|
||||
};
|
||||
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);
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
@@ -18,23 +18,26 @@ app.run(['userService', '$log', '$rootScope', '$location', 'queryStrings', 'navi
|
||||
eventsService.on("app.authenticated", function(evt, data) {
|
||||
|
||||
assetsService._loadInitAssets().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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ function ColorPickerController($scope) {
|
||||
|
||||
$scope.toggleItem = function (color) {
|
||||
|
||||
var currentColor = $scope.model.value.hasOwnProperty("value")
|
||||
var currentColor = ($scope.model.value && $scope.model.value.hasOwnProperty("value"))
|
||||
? $scope.model.value.value
|
||||
: $scope.model.value;
|
||||
|
||||
|
||||
+21
-20
@@ -130,6 +130,9 @@ 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();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -154,26 +157,24 @@ angular.module("umbraco")
|
||||
.controller('Umbraco.PropertyEditors.FileUploadController', fileUploadController)
|
||||
.run(function(mediaHelper, umbRequestHelper, assetsService){
|
||||
if (mediaHelper && mediaHelper.registerFileResolver) {
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
//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;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="fileCount" ng-model="files.length" val-property-validator="validateMandatory"/>
|
||||
<input type="hidden" name="fileCount" ng-model="files.length" val-property-validator="validateMandatory" no-dirty-check />
|
||||
|
||||
</div>
|
||||
|
||||
@@ -99,4 +99,4 @@ module.exports = function (config) {
|
||||
'karma-phantomjs-launcher'
|
||||
]
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
url += "&mode=crop";
|
||||
}
|
||||
}
|
||||
|
||||
var altText = Model.value.altText ?? Model.value.caption ?? string.Empty;
|
||||
|
||||
<img src="@url" alt="@Model.value.caption">
|
||||
<img src="@url" alt="@altText">
|
||||
|
||||
if (Model.value.caption != null)
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<key alias="update">Bijwerken</key>
|
||||
</area>
|
||||
<area alias="assignDomain">
|
||||
<key alias="permissionDenied">Permission denied.</key>
|
||||
<key alias="permissionDenied">Toegang geweigerd.</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">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="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="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>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
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,6 +268,10 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
"helpApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<HelpController>(
|
||||
controller => controller.GetContextHelpForPage("","",""))
|
||||
},
|
||||
{
|
||||
"backOfficeAssetsApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<BackOfficeAssetsController>(
|
||||
controller => controller.GetSupportedMomentLocales())
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -63,6 +63,10 @@ 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!
|
||||
@@ -122,4 +126,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-with-locales.js',
|
||||
'lib/moment/moment.min.js',
|
||||
|
||||
'lib/jquery-ui/jquery-ui.min.js',
|
||||
'lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js',
|
||||
|
||||
@@ -316,6 +316,7 @@
|
||||
<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" />
|
||||
|
||||
Reference in New Issue
Block a user