diff --git a/src/Umbraco.Tests/App.config b/src/Umbraco.Tests/App.config
index 6500cd3741..ef5d8133f6 100644
--- a/src/Umbraco.Tests/App.config
+++ b/src/Umbraco.Tests/App.config
@@ -156,7 +156,7 @@
-
+
@@ -172,7 +172,7 @@
-
+
diff --git a/src/Umbraco.Tests/Controllers/UsersControllerTests.cs b/src/Umbraco.Tests/Controllers/UsersControllerTests.cs
new file mode 100644
index 0000000000..45a4979377
--- /dev/null
+++ b/src/Umbraco.Tests/Controllers/UsersControllerTests.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Formatting;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Web.Configuration;
+using System.Web.Http;
+using System.Web.Http.SelfHost;
+using AutoMapper;
+using Examine.Providers;
+using Microsoft.Owin.Testing;
+using Moq;
+using Newtonsoft.Json;
+using NUnit.Framework;
+using Umbraco.Core;
+using Umbraco.Core.Models;
+using Umbraco.Core.Models.Membership;
+using Umbraco.Core.Persistence.DatabaseModelDefinitions;
+using Umbraco.Tests.TestHelpers;
+using Umbraco.Tests.TestHelpers.ControllerTesting;
+using Umbraco.Tests.TestHelpers.Entities;
+using Umbraco.Web.Editors;
+using Umbraco.Web.Models.ContentEditing;
+using Umbraco.Web.Models.Mapping;
+using Umbraco.Web.WebApi;
+
+namespace Umbraco.Tests.Controllers
+{
+ [DatabaseTestBehavior(DatabaseBehavior.NoDatabasePerFixture)]
+ [RequiresAutoMapperMappings]
+ [TestFixture]
+ public class UsersControllerTests : BaseDatabaseFactoryTest
+ {
+ [Test]
+ public async void GetPagedUsers_Empty()
+ {
+ var runner = new TestRunner((message, helper) => new UsersController(helper.UmbracoContext));
+ var response = await runner.Execute("Users", "GetPagedUsers", HttpMethod.Get);
+
+ var obj = JsonConvert.DeserializeObject>(response.Item2);
+ Assert.AreEqual(0, obj.TotalItems);
+ }
+
+ [Test]
+ public async void GetPagedUsers_10()
+ {
+ var runner = new TestRunner((message, helper) =>
+ {
+ //setup some mocks
+ var userServiceMock = Mock.Get(helper.UmbracoContext.Application.Services.UserService);
+ var users = MockedUser.CreateMulipleUsers(10);
+ long outVal = 10;
+ userServiceMock.Setup(service => service.GetAll(It.IsAny(), It.IsAny(), out outVal, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()))
+ .Returns(() => users);
+
+ return new UsersController(helper.UmbracoContext);
+ });
+ var response = await runner.Execute("Users", "GetPagedUsers", HttpMethod.Get);
+
+ var obj = JsonConvert.DeserializeObject>(response.Item2);
+ Assert.AreEqual(10, obj.TotalItems);
+ Assert.AreEqual(10, obj.Items.Count());
+ }
+ }
+}
diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingExtensions.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingExtensions.cs
new file mode 100644
index 0000000000..f7d457f0d1
--- /dev/null
+++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingExtensions.cs
@@ -0,0 +1,18 @@
+using System;
+using Microsoft.Owin.Extensions;
+using Owin;
+
+namespace Umbraco.Tests.TestHelpers.ControllerTesting
+{
+ public static class AuthenticateEverythingExtensions
+ {
+ public static IAppBuilder AuthenticateEverything(this IAppBuilder app)
+ {
+ if (app == null)
+ throw new ArgumentNullException("app");
+ app.Use(typeof(AuthenticateEverythingMiddleware), (object)app, (object)new AuthenticateEverythingMiddleware.AuthenticateEverythingAuthenticationOptions());
+ app.UseStageMarker(PipelineStage.Authenticate);
+ return app;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs
new file mode 100644
index 0000000000..2dbfa757f2
--- /dev/null
+++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.Owin;
+using Microsoft.Owin.Security;
+using Microsoft.Owin.Security.Infrastructure;
+using Owin;
+using Umbraco.Core.Security;
+
+namespace Umbraco.Tests.TestHelpers.ControllerTesting
+{
+ public class AuthenticateEverythingMiddleware : AuthenticationMiddleware
+ {
+ public AuthenticateEverythingMiddleware(OwinMiddleware next, IAppBuilder app, AuthenticationOptions options)
+ : base(next, options)
+ {
+ }
+
+ protected override AuthenticationHandler CreateHandler()
+ {
+ return new AuthenticateEverythingHandler();
+ }
+
+ public class AuthenticateEverythingHandler : AuthenticationHandler
+ {
+ protected override Task AuthenticateCoreAsync()
+ {
+ var identity = new UmbracoBackOfficeIdentity(
+ new UserData(Guid.NewGuid().ToString())
+ {
+ Id = 0,
+ Roles = new[] { "admin" },
+ AllowedApplications = new[] { "content", "media", "members" },
+ Culture = "en-US",
+ RealName = "Admin",
+ StartContentNode = -1,
+ StartMediaNode = -1,
+ Username = "admin"
+ });
+
+ return Task.FromResult(new AuthenticationTicket(identity,
+ new AuthenticationProperties()
+ {
+ ExpiresUtc = DateTime.Now.AddDays(1)
+ }));
+ }
+ }
+
+ public class AuthenticateEverythingAuthenticationOptions : AuthenticationOptions
+ {
+ public AuthenticateEverythingAuthenticationOptions()
+ : base("AuthenticateEverything")
+ {
+ AuthenticationMode = AuthenticationMode.Active;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/SpecificAssemblyResolver.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/SpecificAssemblyResolver.cs
new file mode 100644
index 0000000000..b301952c92
--- /dev/null
+++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/SpecificAssemblyResolver.cs
@@ -0,0 +1,21 @@
+using System.Collections.Generic;
+using System.Reflection;
+using System.Web.Http.Dispatcher;
+
+namespace Umbraco.Tests.TestHelpers.ControllerTesting
+{
+ public class SpecificAssemblyResolver : IAssembliesResolver
+ {
+ private readonly Assembly[] _assemblies;
+
+ public SpecificAssemblyResolver(Assembly[] assemblies)
+ {
+ _assemblies = assemblies;
+ }
+
+ public ICollection GetAssemblies()
+ {
+ return _assemblies;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivator.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivator.cs
new file mode 100644
index 0000000000..81cdeccbfe
--- /dev/null
+++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivator.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Net.Http;
+using System.Web.Http;
+using Umbraco.Web;
+
+namespace Umbraco.Tests.TestHelpers.ControllerTesting
+{
+ public class TestControllerActivator : TestControllerActivatorBase
+ {
+ private readonly Func _factory;
+
+ public TestControllerActivator(Func factory)
+ {
+ _factory = factory;
+ }
+
+ protected override ApiController CreateController(Type controllerType, HttpRequestMessage msg, UmbracoHelper helper)
+ {
+ return _factory(msg, helper);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs
new file mode 100644
index 0000000000..bebf6ab1e2
--- /dev/null
+++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Linq;
+using System.Net.Http;
+using System.Web;
+using System.Web.Http;
+using System.Web.Http.Controllers;
+using System.Web.Http.Dispatcher;
+using System.Web.Security;
+using Moq;
+using Semver;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Configuration.UmbracoSettings;
+using Umbraco.Core.Dictionary;
+using Umbraco.Core.Logging;
+using Umbraco.Core.Models;
+using Umbraco.Core.Models.Membership;
+using Umbraco.Core.Persistence;
+using Umbraco.Core.Persistence.SqlSyntax;
+using Umbraco.Core.Profiling;
+using Umbraco.Core.Security;
+using Umbraco.Core.Services;
+using Umbraco.Web;
+using Umbraco.Web.Routing;
+using Umbraco.Web.Security;
+using Umbraco.Web.WebApi;
+
+namespace Umbraco.Tests.TestHelpers.ControllerTesting
+{
+ ///
+ /// Used to mock all of the services required for re-mocking and testing controllers
+ ///
+ ///
+ /// A more complete version of this is found in the Umbraco REST API project but this has the basics covered
+ ///
+ public abstract class TestControllerActivatorBase : DefaultHttpControllerActivator, IHttpControllerActivator
+ {
+ IHttpController IHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
+ {
+ if (typeof(UmbracoApiControllerBase).IsAssignableFrom(controllerType))
+ {
+ var owinContext = request.GetOwinContext();
+
+ var mockedUserService = Mock.Of();
+
+ var mockedMigrationService = new Mock();
+ //set it up to return anything so that the app ctx is 'Configured'
+ mockedMigrationService.Setup(x => x.FindEntry(It.IsAny(), It.IsAny())).Returns(Mock.Of());
+
+ var serviceContext = new ServiceContext(
+ userService: mockedUserService,
+ migrationEntryService: mockedMigrationService.Object);
+
+ //ensure the configuration matches the current version for tests
+ SettingsForTests.ConfigurationStatus = UmbracoVersion.GetSemanticVersion().ToSemanticString();
+
+ //new app context
+ var dbCtx = new Mock(Mock.Of(), Mock.Of(), Mock.Of(), "test");
+ //ensure these are set so that the appctx is 'Configured'
+ dbCtx.Setup(x => x.CanConnect).Returns(true);
+ dbCtx.Setup(x => x.IsDatabaseConfigured).Returns(true);
+ var appCtx = ApplicationContext.EnsureContext(
+ dbCtx.Object,
+ //pass in mocked services
+ serviceContext,
+ CacheHelper.CreateDisabledCacheHelper(),
+ new ProfilingLogger(Mock.Of(), Mock.Of()),
+ true);
+
+ //httpcontext with an auth'd user
+ var httpContext = Mock.Of(
+ http => http.User == owinContext.Authentication.User
+ //ensure the request exists with a cookies collection
+ && http.Request == Mock.Of(r => r.Cookies == new HttpCookieCollection()));
+ //chuck it into the props since this is what MS does when hosted and it's needed there
+ request.Properties["MS_HttpContext"] = httpContext;
+
+ var backofficeIdentity = (UmbracoBackOfficeIdentity)owinContext.Authentication.User.Identity;
+
+ var webSecurity = new Mock(null, null);
+
+ //mock CurrentUser
+ webSecurity.Setup(x => x.CurrentUser)
+ .Returns(Mock.Of(u => u.IsApproved == true
+ && u.IsLockedOut == false
+ && u.AllowedSections == backofficeIdentity.AllowedApplications
+ && u.Email == "admin@admin.com"
+ && u.Id == (int) backofficeIdentity.Id
+ && u.Language == "en"
+ && u.Name == backofficeIdentity.RealName
+ && u.StartContentId == backofficeIdentity.StartContentNode
+ && u.StartMediaId == backofficeIdentity.StartMediaNode
+ && u.Username == backofficeIdentity.Username));
+
+ //mock Validate
+ webSecurity.Setup(x => x.ValidateCurrentUser())
+ .Returns(() => true);
+ webSecurity.Setup(x => x.UserHasAppAccess(It.IsAny(), It.IsAny()))
+ .Returns(() => true);
+
+ var umbCtx = UmbracoContext.EnsureContext(
+ //set the user of the HttpContext
+ httpContext,
+ appCtx,
+ webSecurity.Object,
+ Mock.Of(section => section.WebRouting == Mock.Of(routingSection => routingSection.UrlProviderMode == UrlProviderMode.Auto.ToString())),
+ Enumerable.Empty(),
+ true); //replace it
+
+ var urlHelper = new Mock();
+ urlHelper.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()))
+ .Returns("/hello/world/1234");
+
+ var membershipHelper = new MembershipHelper(umbCtx, Mock.Of(), Mock.Of());
+
+ var mockedTypedContent = Mock.Of();
+
+ var umbHelper = new UmbracoHelper(umbCtx,
+ Mock.Of(),
+ mockedTypedContent,
+ Mock.Of(),
+ Mock.Of(),
+ Mock.Of(),
+ new UrlProvider(umbCtx, new[]
+ {
+ urlHelper.Object
+ }, UrlProviderMode.Auto),
+ Mock.Of(),
+ Mock.Of(),
+ membershipHelper);
+
+ return CreateController(controllerType, request, umbHelper);
+ }
+ //default
+ return base.Create(request, controllerDescriptor, controllerType);
+ }
+
+ protected abstract ApiController CreateController(Type controllerType, HttpRequestMessage msg, UmbracoHelper helper);
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestRunner.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestRunner.cs
new file mode 100644
index 0000000000..12ffda5e04
--- /dev/null
+++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestRunner.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading.Tasks;
+using System.Web.Http;
+using Microsoft.Owin.Testing;
+using Newtonsoft.Json;
+using NUnit.Framework;
+using Umbraco.Core;
+using Umbraco.Web;
+using Umbraco.Web.WebApi;
+
+namespace Umbraco.Tests.TestHelpers.ControllerTesting
+{
+ public class TestRunner
+ {
+ private readonly Func _controllerFactory;
+
+ public TestRunner(Func controllerFactory)
+ {
+ _controllerFactory = controllerFactory;
+ }
+
+ public async Task> Execute(string controllerName, string actionName, HttpMethod method)
+ {
+ var startup = new TestStartup(
+ configuration =>
+ {
+ configuration.Routes.MapHttpRoute("Default",
+ routeTemplate: "{controller}/{action}/{id}",
+ defaults: new { controller = controllerName, action = actionName, id = RouteParameter.Optional });
+ },
+ _controllerFactory);
+
+ using (var server = TestServer.Create(builder => startup.Configuration(builder)))
+ {
+ var request = new HttpRequestMessage
+ {
+ RequestUri = new Uri("http://testserver/"),
+ Method = method,
+ };
+
+ request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+
+ Console.WriteLine(request);
+ var response = await server.HttpClient.SendAsync(request);
+ Console.WriteLine(response);
+
+ string json = "";
+ if (response.IsSuccessStatusCode == false)
+ {
+ WriteResponseError(response);
+ }
+ else
+ {
+ json = (await ((StreamContent)response.Content).ReadAsStringAsync()).TrimStart(AngularJsonMediaTypeFormatter.XsrfPrefix);
+ var deserialized = JsonConvert.DeserializeObject(json);
+ Console.Write(JsonConvert.SerializeObject(deserialized, Formatting.Indented));
+ }
+
+ Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
+ return Tuple.Create(response, json);
+ }
+ }
+
+ private static void WriteResponseError(HttpResponseMessage response)
+ {
+ var result = response.Content.ReadAsStringAsync().Result;
+ Console.Out.WriteLine("Http operation unsuccessfull");
+ Console.Out.WriteLine(string.Format("Status: '{0}'", response.StatusCode));
+ Console.Out.WriteLine(string.Format("Reason: '{0}'", response.ReasonPhrase));
+ Console.Out.WriteLine(result);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestStartup.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestStartup.cs
new file mode 100644
index 0000000000..1bbb03095f
--- /dev/null
+++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestStartup.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Net.Http;
+using System.Web.Http;
+using System.Web.Http.Dispatcher;
+using System.Web.Http.ExceptionHandling;
+using System.Web.Http.Tracing;
+using Owin;
+using Umbraco.Web;
+using Umbraco.Web.Editors;
+using Umbraco.Web.WebApi;
+
+namespace Umbraco.Tests.TestHelpers.ControllerTesting
+{
+ ///
+ /// Startup class for the self-hosted web server works for OWIN and WebAPI
+ ///
+ public class TestStartup
+ {
+ private readonly Func _controllerFactory;
+ private readonly Action _initialize;
+
+ public TestStartup(Action initialize, Func controllerFactory)
+ {
+ _controllerFactory = controllerFactory;
+ _initialize = initialize;
+ }
+
+ public void Configuration(IAppBuilder app)
+ {
+ var httpConfig = new HttpConfiguration();
+
+ //TODO: Enable this if you can't see the errors produced
+ //var traceWriter = httpConfig.EnableSystemDiagnosticsTracing();
+ //traceWriter.IsVerbose = true;
+ //traceWriter.MinimumLevel = TraceLevel.Debug;
+
+ httpConfig.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
+
+ // Add in a simple exception tracer so we can see what is causing the 500 Internal Server Error
+ httpConfig.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());
+
+ httpConfig.Services.Replace(typeof(IAssembliesResolver), new SpecificAssemblyResolver(new[] { typeof(UsersController).Assembly }));
+ httpConfig.Services.Replace(typeof(IHttpControllerActivator), new TestControllerActivator(_controllerFactory));
+ httpConfig.Services.Replace(typeof(IHttpControllerSelector), new NamespaceHttpControllerSelector(httpConfig));
+
+ //auth everything
+ app.AuthenticateEverything();
+
+ _initialize(httpConfig);
+
+ app.UseWebApi(httpConfig);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TraceExceptionLogger.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TraceExceptionLogger.cs
new file mode 100644
index 0000000000..faf5870cbb
--- /dev/null
+++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TraceExceptionLogger.cs
@@ -0,0 +1,16 @@
+using System.Diagnostics;
+using System.Web.Http.ExceptionHandling;
+
+namespace Umbraco.Tests.TestHelpers.ControllerTesting
+{
+ ///
+ /// Traces any errors for WebApi to the output window
+ ///
+ public class TraceExceptionLogger : ExceptionLogger
+ {
+ public override void Log(ExceptionLoggerContext context)
+ {
+ Trace.TraceError(context.ExceptionContext.Exception.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index 498bc35c86..651ae301ce 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -76,8 +76,23 @@
..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll
-
- ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll
+
+ ..\packages\Microsoft.Owin.3.1.0\lib\net45\Microsoft.Owin.dll
+
+
+ ..\packages\Microsoft.Owin.Host.HttpListener.3.1.0\lib\net45\Microsoft.Owin.Host.HttpListener.dll
+
+
+ ..\packages\Microsoft.Owin.Host.SystemWeb.3.1.0\lib\net45\Microsoft.Owin.Host.SystemWeb.dll
+
+
+ ..\packages\Microsoft.Owin.Hosting.3.1.0\lib\net45\Microsoft.Owin.Hosting.dll
+
+
+ ..\packages\Microsoft.Owin.Security.3.1.0\lib\net45\Microsoft.Owin.Security.dll
+
+
+ ..\packages\Microsoft.Owin.Testing.3.1.0\lib\net45\Microsoft.Owin.Testing.dll
..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
@@ -128,9 +143,14 @@
..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll
-
- ..\packages\Microsoft.AspNet.WebApi.SelfHost.4.0.30506.0\lib\net40\System.Web.Http.SelfHost.dll
- True
+
+ ..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3\lib\net45\System.Web.Http.Owin.dll
+
+
+ ..\packages\Microsoft.AspNet.WebApi.SelfHost.5.2.3\lib\net45\System.Web.Http.SelfHost.dll
+
+
+ ..\packages\Microsoft.AspNet.WebApi.Tracing.5.2.3\lib\net45\System.Web.Http.Tracing.dll
..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll
@@ -162,6 +182,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/Umbraco.Tests/packages.config b/src/Umbraco.Tests/packages.config
index a9cbce1aad..1577212ffe 100644
--- a/src/Umbraco.Tests/packages.config
+++ b/src/Umbraco.Tests/packages.config
@@ -1,6 +1,5 @@
-
@@ -12,10 +11,18 @@
-
+
+
+
+
-
+
+
+
+
+
+
diff --git a/src/Umbraco.Web/Editors/UsersController.cs b/src/Umbraco.Web/Editors/UsersController.cs
index 0d48b96bd0..e34d98e902 100644
--- a/src/Umbraco.Web/Editors/UsersController.cs
+++ b/src/Umbraco.Web/Editors/UsersController.cs
@@ -37,7 +37,7 @@ namespace Umbraco.Web.Editors
: base(umbracoContext)
{
}
-
+
///
/// Gets a user by Id
///
@@ -55,16 +55,21 @@ namespace Umbraco.Web.Editors
public PagedResult GetPagedUsers(
int pageNumber = 1,
- int pageSize = 0,
+ int pageSize = 10,
string orderBy = "username",
Direction orderDirection = Direction.Ascending,
- string[] userGroups = null,
+ [FromUri]string[] userGroups = null,
string filter = "")
{
long pageIndex = pageNumber - 1;
long total;
var result = Services.UserService.GetAll(pageIndex, pageSize, out total, orderBy, orderDirection, null, userGroups, filter);
+ if (total == 0)
+ {
+ return new PagedResult(0, 0, 0);
+ }
+
return new PagedResult(total, pageNumber, pageSize)
{
Items = Mapper.Map>(result)
diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs
index e459bb9eb4..05407a93e5 100644
--- a/src/Umbraco.Web/Security/WebSecurity.cs
+++ b/src/Umbraco.Web/Security/WebSecurity.cs
@@ -395,7 +395,7 @@ namespace Umbraco.Web.Security
///
///
///
- internal bool UserHasAppAccess(string app, IUser user)
+ internal virtual bool UserHasAppAccess(string app, IUser user)
{
var apps = user.AllowedSections;
return apps.Any(uApp => uApp.InvariantEquals(app));
diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs
index 90f4e4df03..dbb165a526 100644
--- a/src/Umbraco.Web/UmbracoContext.cs
+++ b/src/Umbraco.Web/UmbracoContext.cs
@@ -259,7 +259,7 @@ namespace Umbraco.Web
var requestUrl = new Uri("http://localhost");
var request = GetRequestFromContext();
- if (request != null)
+ if (request != null && request.Url != null)
{
requestUrl = request.Url;
}
diff --git a/src/Umbraco.Web/WebApi/AngularJsonMediaTypeFormatter.cs b/src/Umbraco.Web/WebApi/AngularJsonMediaTypeFormatter.cs
index 66a79376aa..8dca204597 100644
--- a/src/Umbraco.Web/WebApi/AngularJsonMediaTypeFormatter.cs
+++ b/src/Umbraco.Web/WebApi/AngularJsonMediaTypeFormatter.cs
@@ -21,6 +21,8 @@ namespace Umbraco.Web.WebApi
public class AngularJsonMediaTypeFormatter : JsonMediaTypeFormatter
{
+ public const string XsrfPrefix = ")]}',\n";
+
///
/// This will prepend the special chars to the stream output that angular will strip
///
@@ -30,24 +32,25 @@ namespace Umbraco.Web.WebApi
///
///
///
- public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
+ public override async Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
-
if (type == null) throw new ArgumentNullException("type");
if (writeStream == null) throw new ArgumentNullException("writeStream");
var effectiveEncoding = SelectCharacterEncoding(content == null ? null : content.Headers);
- using (var streamWriter = new StreamWriter(writeStream, effectiveEncoding))
+ using (var streamWriter = new StreamWriter(writeStream, effectiveEncoding,
+ //we are only writing a few chars so we don't need to allocate a large buffer
+ 128,
+ //this is important! We don't want to close the stream, the base class is in charge of stream management, we just want to write to it.
+ leaveOpen:true))
{
//write the special encoding for angular json to the start
// (see: http://docs.angularjs.org/api/ng.$http)
- streamWriter.Write(")]}',\n");
+ streamWriter.Write(XsrfPrefix);
streamWriter.Flush();
- return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
+ await base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
}
-
-
}
}
diff --git a/src/Umbraco.Web/WebApi/Filters/UmbracoApplicationAuthorizeAttribute.cs b/src/Umbraco.Web/WebApi/Filters/UmbracoApplicationAuthorizeAttribute.cs
index 23e0fde1c2..c305ad3339 100644
--- a/src/Umbraco.Web/WebApi/Filters/UmbracoApplicationAuthorizeAttribute.cs
+++ b/src/Umbraco.Web/WebApi/Filters/UmbracoApplicationAuthorizeAttribute.cs
@@ -33,10 +33,12 @@ namespace Umbraco.Web.WebApi.Filters
{
return true;
}
-
- return UmbracoContext.Current.Security.CurrentUser != null
+
+ var authorized = UmbracoContext.Current.Security.CurrentUser != null
&& _appNames.Any(app => UmbracoContext.Current.Security.UserHasAppAccess(
app, UmbracoContext.Current.Security.CurrentUser));
+
+ return authorized;
}
}
}
\ No newline at end of file