diff --git a/src/Umbraco.Core/Persistence/Querying/IQuery.cs b/src/Umbraco.Core/Persistence/Querying/IQuery.cs
index ae986baddc..cd08274c1b 100644
--- a/src/Umbraco.Core/Persistence/Querying/IQuery.cs
+++ b/src/Umbraco.Core/Persistence/Querying/IQuery.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq.Expressions;
namespace Umbraco.Core.Persistence.Querying
@@ -16,6 +17,11 @@ namespace Umbraco.Core.Persistence.Querying
/// This instance so calls to this method are chainable
IQuery Where(Expression> predicate);
-
+ ///
+ /// Adds a set of OR-ed where clauses to the query.
+ ///
+ ///
+ /// This instance so calls to this method are chainable.
+ IQuery WhereAny(IEnumerable>> predicates);
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/Querying/Query.cs b/src/Umbraco.Core/Persistence/Querying/Query.cs
index 6213ca5ed6..d49296c6d0 100644
--- a/src/Umbraco.Core/Persistence/Querying/Query.cs
+++ b/src/Umbraco.Core/Persistence/Querying/Query.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
+using System.Text;
namespace Umbraco.Core.Persistence.Querying
{
@@ -39,6 +40,50 @@ namespace Umbraco.Core.Persistence.Querying
return this;
}
+ ///
+ /// Adds a set of OR-ed where clauses to the query.
+ ///
+ ///
+ /// This instance so calls to this method are chainable.
+ public virtual IQuery WhereAny(IEnumerable>> predicates)
+ {
+ if (predicates == null) return this;
+
+ StringBuilder sb = null;
+ List parameters = null;
+ Sql sql = null;
+ foreach (var predicate in predicates)
+ {
+ // see notes in Where()
+ var expressionHelper = new ModelToSqlExpressionVisitor();
+ var whereExpression = expressionHelper.Visit(predicate);
+
+ if (sb == null)
+ {
+ sb = new StringBuilder("(");
+ parameters = new List();
+ sql = new Sql();
+ }
+ else
+ {
+ sb.Append(" OR ");
+ sql.Append(" OR ");
+ }
+
+ sb.Append(whereExpression);
+ parameters.AddRange(expressionHelper.GetSqlParameters());
+ sql.Append(whereExpression, expressionHelper.GetSqlParameters());
+ }
+
+ if (sb == null) return this;
+
+ sb.Append(")");
+ //_wheres.Add(Tuple.Create(sb.ToString(), parameters.ToArray()));
+ _wheres.Add(Tuple.Create("(" + sql.SQL + ")", sql.Arguments));
+
+ return this;
+ }
+
///
/// Returns all translated where clauses and their sql parameters
///
diff --git a/src/Umbraco.Core/Persistence/Repositories/UserGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UserGroupRepository.cs
index 3d291d5e07..be7a31e298 100644
--- a/src/Umbraco.Core/Persistence/Repositories/UserGroupRepository.cs
+++ b/src/Umbraco.Core/Persistence/Repositories/UserGroupRepository.cs
@@ -167,7 +167,7 @@ namespace Umbraco.Core.Persistence.Repositories
_permissionRepository.AssignPermission(groupId, permission, entityIds);
}
- #region Overrides of RepositoryBase
+ #region Overrides of RepositoryBase
protected override IUserGroup PerformGet(int id)
{
diff --git a/src/Umbraco.Core/Services/EntityService.cs b/src/Umbraco.Core/Services/EntityService.cs
index 04d6c276b2..ecf1b5a216 100644
--- a/src/Umbraco.Core/Services/EntityService.cs
+++ b/src/Umbraco.Core/Services/EntityService.cs
@@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
using Umbraco.Core.Cache;
using Umbraco.Core.CodeAnnotations;
using Umbraco.Core.Events;
@@ -361,6 +364,40 @@ namespace Umbraco.Core.Services
return contents;
}
}
+ ///
+ /// Returns a paged collection of descendants.
+ ///
+ public IEnumerable GetPagedDescendants(IEnumerable ids, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
+ string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "")
+ {
+ var objectTypeId = umbracoObjectType.GetGuid();
+ using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
+ {
+ var repository = RepositoryFactory.CreateEntityRepository(uow);
+
+ var query = Query.Builder;
+ var idsA = ids.ToArray();
+ if (idsA.All(x => x != Constants.System.Root))
+ {
+ var clauses = new List>>();
+ foreach (var id in idsA)
+ {
+ var qid = id;
+ clauses.Add(x => x.Path.SqlContains(string.Format(",{0},", qid), TextColumnType.NVarchar) || x.Path.SqlEndsWith(string.Format(",{0}", qid), TextColumnType.NVarchar));
+ }
+ query.WhereAny(clauses);
+ }
+
+ IQuery filterQuery = null;
+ if (filter.IsNullOrWhiteSpace() == false)
+ {
+ filterQuery = Query.Builder.Where(x => x.Name.Contains(filter));
+ }
+
+ var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
+ return contents;
+ }
+ }
///
/// Returns a paged collection of descendants from the root
diff --git a/src/Umbraco.Core/Services/IEntityService.cs b/src/Umbraco.Core/Services/IEntityService.cs
index 82e5227cf2..f6c75c2e98 100644
--- a/src/Umbraco.Core/Services/IEntityService.cs
+++ b/src/Umbraco.Core/Services/IEntityService.cs
@@ -175,6 +175,12 @@ namespace Umbraco.Core.Services
IEnumerable GetPagedDescendants(int id, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "");
+ ///
+ /// Returns a paged collection of descendants
+ ///
+ IEnumerable GetPagedDescendants(IEnumerable ids, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
+ string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "");
+
///
/// Returns a paged collection of descendants from the root
///
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index f9b1c7a752..f25c1c9c79 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -118,6 +118,7 @@
+
diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs
index 7bf29bb0ab..57d1f80995 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs
+++ b/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs
@@ -64,18 +64,18 @@ namespace Umbraco.Tests.Persistence.Repositories
using (var repository = CreateRepository(unitOfWork))
{
- var userType1 = MockedUserGroup.CreateUserGroup("1");
- var userType2 = MockedUserGroup.CreateUserGroup("2");
+ var userGroup1 = MockedUserGroup.CreateUserGroup("1");
+ var userGroup2 = MockedUserGroup.CreateUserGroup("2");
// Act
- repository.AddOrUpdate(userType1);
+ repository.AddOrUpdate(userGroup1);
unitOfWork.Commit();
- repository.AddOrUpdate(userType2);
+ repository.AddOrUpdate(userGroup2);
unitOfWork.Commit();
// Assert
- Assert.That(userType1.HasIdentity, Is.True);
- Assert.That(userType2.HasIdentity, Is.True);
+ Assert.That(userGroup1.HasIdentity, Is.True);
+ Assert.That(userGroup2.HasIdentity, Is.True);
}
}
@@ -209,10 +209,10 @@ namespace Umbraco.Tests.Persistence.Repositories
var unitOfWork = provider.GetUnitOfWork();
using (var repository = CreateRepository(unitOfWork))
{
- var userTypes = CreateAndCommitMultipleUserGroups(repository, unitOfWork);
+ var userGroups = CreateAndCommitMultipleUserGroups(repository, unitOfWork);
// Act
- var result = repository.GetAll(userTypes[0].Id, userTypes[1].Id);
+ var result = repository.GetAll(userGroups[0].Id, userGroups[1].Id);
// Assert
Assert.That(result, Is.Not.Null);
@@ -249,10 +249,10 @@ namespace Umbraco.Tests.Persistence.Repositories
var unitOfWork = provider.GetUnitOfWork();
using (var repository = CreateRepository(unitOfWork))
{
- var userTypes = CreateAndCommitMultipleUserGroups(repository, unitOfWork);
+ var userGroups = CreateAndCommitMultipleUserGroups(repository, unitOfWork);
// Act
- var exists = repository.Exists(userTypes[0].Id);
+ var exists = repository.Exists(userGroups[0].Id);
// Assert
Assert.That(exists, Is.True);
@@ -267,7 +267,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var unitOfWork = provider.GetUnitOfWork();
using (var repository = CreateRepository(unitOfWork))
{
- var userTypes = CreateAndCommitMultipleUserGroups(repository, unitOfWork);
+ var userGroups = CreateAndCommitMultipleUserGroups(repository, unitOfWork);
// Act
var query = Query.Builder.Where(x => x.Alias == "testUserGroup1" || x.Alias == "testUserGroup2");
diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs
index 88ecb50f2f..334c4f98c2 100644
--- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs
+++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs
@@ -36,7 +36,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var tagRepository = new TagRepository(unitOfWork, CacheHelper, Mock.Of(), SqlSyntax);
var repository = new MediaRepository(unitOfWork, CacheHelper, Mock.Of(), SqlSyntax, mediaTypeRepository, tagRepository, Mock.Of());
return repository;
- }
+ }
private ContentRepository CreateContentRepository(IScopeUnitOfWork unitOfWork, out IContentTypeRepository contentTypeRepository)
{
@@ -51,7 +51,7 @@ namespace Umbraco.Tests.Persistence.Repositories
contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, templateRepository);
var repository = new ContentRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, contentTypeRepository, templateRepository, tagRepository, Mock.Of());
return repository;
- }
+ }
private UserRepository CreateRepository(IScopeUnitOfWork unitOfWork)
{
@@ -86,7 +86,7 @@ namespace Umbraco.Tests.Persistence.Repositories
[Test]
public void Can_Perform_Add_With_Group()
{
- var group = MockedUserGroup.CreateUserGroup();
+ var group = MockedUserGroup.CreateUserGroup();
// Arrange
var provider = new PetaPocoUnitOfWorkProvider(Logger);
@@ -95,22 +95,22 @@ namespace Umbraco.Tests.Persistence.Repositories
{
repository.AddOrUpdate(group);
unitOfWork.Commit();
- }
+ }
using (var repository = CreateRepository(unitOfWork))
{
IUser user = MockedUser.CreateUser();
- user.AddGroup(group.ToReadOnlyGroup());
+ user.AddGroup(group.ToReadOnlyGroup());
// Act
repository.AddOrUpdate(user);
unitOfWork.Commit();
- user = repository.Get(user.Id);
+ user = repository.Get(user.Id);
// Assert
Assert.That(user.HasIdentity, Is.True);
- Assert.AreEqual(1, user.Groups.Count());
+ Assert.AreEqual(1, user.Groups.Count());
Assert.AreEqual(group.Alias, user.Groups.ElementAt(0).Alias);
}
}
@@ -165,7 +165,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var ct = MockedContentTypes.CreateBasicContentType("test");
var content = MockedContent.CreateBasicContent(ct);
var mt = MockedContentTypes.CreateSimpleMediaType("testmedia", "TestMedia");
- var media = MockedMedia.CreateSimpleMedia(mt, "asdf", -1);
+ var media = MockedMedia.CreateSimpleMedia(mt, "asdf", -1);
// Arrange
var provider = new PetaPocoUnitOfWorkProvider(Logger);
@@ -173,8 +173,8 @@ namespace Umbraco.Tests.Persistence.Repositories
IContentTypeRepository contentTypeRepo;
IMediaTypeRepository mediaTypeRepo;
using (var contentRepository = CreateContentRepository(unitOfWork, out contentTypeRepo))
- using (var mediaRepository = CreateMediaRepository(unitOfWork, out mediaTypeRepo))
- using (contentTypeRepo)
+ using (var mediaRepository = CreateMediaRepository(unitOfWork, out mediaTypeRepo))
+ using (contentTypeRepo)
using(mediaTypeRepo)
using (var userRepository = CreateRepository(unitOfWork))
using (var userGroupRepository = CreateUserGroupRepository(unitOfWork))
@@ -185,7 +185,7 @@ namespace Umbraco.Tests.Persistence.Repositories
contentRepository.AddOrUpdate(content);
mediaRepository.AddOrUpdate(media);
- unitOfWork.Commit();
+ unitOfWork.Commit();
var user = CreateAndCommitUserWithGroup(userRepository, userGroupRepository, unitOfWork);
@@ -422,7 +422,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var group = MockedUserGroup.CreateUserGroup();
userGroupRepository.AddOrUpdateGroupWithUsers(@group, new[] {user.Id});
- unitOfWork.Commit();
+ unitOfWork.Commit();
return user;
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/usergroups.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/usergroups.resource.js
index fad2820f56..90d9e58736 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/usergroups.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/usergroups.resource.js
@@ -59,11 +59,23 @@
"Failed to retrieve user groups");
}
+ function deleteUserGroups(userGroupIds) {
+ var query = "userGroupIds=" + userGroupIds.join("&userGroupIds=");
+ return umbRequestHelper.resourcePromise(
+ $http.post(
+ umbRequestHelper.getApiUrl(
+ "userGroupsApiBaseUrl",
+ "PostDeleteUserGroups",
+ query)),
+ 'Failed to delete user groups');
+ }
+
var resource = {
saveUserGroup: saveUserGroup,
getUserGroup: getUserGroup,
getUserGroups: getUserGroups,
- getUserGroupScaffold: getUserGroupScaffold
+ getUserGroupScaffold: getUserGroupScaffold,
+ deleteUserGroups: deleteUserGroups
};
return resource;
diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js
index 706142dd18..0acd30afe0 100644
--- a/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js
@@ -55,6 +55,18 @@
'Failed to enable the users ' + userIds.join(","));
}
+ function setUserGroupsOnUsers(userGroups, userIds) {
+ var userGroupAliases = userGroups.map(function(o) { return o.alias; });
+ var query = "userGroupAliases=" + userGroupAliases.join("&userGroupAliases=") + "&userIds=" + userIds.join("&userIds=");
+ return umbRequestHelper.resourcePromise(
+ $http.post(
+ umbRequestHelper.getApiUrl(
+ "userApiBaseUrl",
+ "PostSetUserGroupsOnUsers",
+ query)),
+ 'Failed to set user groups ' + userGroupAliases.join(",") + ' on the users ' + userIds.join(","));
+ }
+
function getPagedResults(options) {
var defaults = {
pageSize: 25,
@@ -173,6 +185,7 @@
var resource = {
disableUsers: disableUsers,
enableUsers: enableUsers,
+ setUserGroupsOnUsers: setUserGroupsOnUsers,
getPagedResults: getPagedResults,
getUser: getUser,
createUser: createUser,
diff --git a/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js
index acc8c781dd..07539b79d2 100644
--- a/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js
@@ -22,7 +22,7 @@
vm.enableUser = enableUser;
vm.clearAvatar = clearAvatar;
vm.save = save;
- vm.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB"
+ vm.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB";
vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes);
vm.toggleChangePassword = toggleChangePassword;
vm.emailIsUsername = true;
@@ -56,8 +56,7 @@
vm.loading = false;
});
-
- });
+ });
}
function toggleChangePassword() {
@@ -91,13 +90,9 @@
//the user has a password if they are not states: Invited, NoCredentials
vm.changePasswordModel.config.hasPassword = vm.user.userState !== 3 && vm.user.userState !== 4;
-
}, function (err) {
-
vm.page.saveButtonState = "error";
-
});
-
}
function goToPage(ancestor) {
@@ -303,7 +298,6 @@
});
}
-
function makeBreadcrumbs() {
vm.breadcrumbs = [
{
@@ -322,9 +316,6 @@
}
init();
-
}
-
angular.module("umbraco").controller("Umbraco.Editors.Users.UserController", UserEditController);
-
})();
diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js
index f10cd8e530..5c30f1354e 100644
--- a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js
@@ -1,7 +1,7 @@
(function () {
"use strict";
- function UserGroupsController($scope, $timeout, $location, userGroupsResource) {
+ function UserGroupsController($scope, $timeout, $location, userGroupsResource, formHelper) {
var vm = this;
@@ -12,6 +12,7 @@
vm.clickUserGroup = clickUserGroup;
vm.clearSelection = clearSelection;
vm.selectUserGroup = selectUserGroup;
+ vm.deleteUserGroups = deleteUserGroups;
function onInit() {
@@ -57,6 +58,18 @@
}
}
+ function deleteUserGroups() {
+ if (vm.selection.length > 0) {
+ userGroupsResource.deleteUserGroups(vm.selection).then(function (data) {
+ clearSelection();
+ onInit();
+ formHelper.showNotifications(data);
+ }, function(error) {
+ formHelper.showNotifications(error.data);
+ });
+ }
+ }
+
function clearSelection() {
angular.forEach(vm.userGroups, function (userGroup) {
userGroup.selected = false;
diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.html b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.html
index 738fc4f654..38dc7a77f6 100644
--- a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.html
+++ b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.html
@@ -32,7 +32,7 @@
type="button"
label="Delete"
icon="icon-trash"
- action="vm.deleteUserGroup()"
+ action="vm.deleteUserGroups()"
size="xs">
diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js
index 881c4931ff..abbacf5040 100644
--- a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js
@@ -24,6 +24,8 @@
vm.newUser.userGroups = [];
vm.usersViewState = 'overview';
+ vm.selectedBulkUserGroups = [];
+
vm.allowDisableUser = true;
vm.allowEnableUser = true;
vm.allowSetUserGroup = true;
@@ -73,6 +75,7 @@
vm.clickUser = clickUser;
vm.disableUsers = disableUsers;
vm.enableUsers = enableUsers;
+ vm.openBulkUserGroupPicker = openBulkUserGroupPicker;
vm.openUserGroupPicker = openUserGroupPicker;
vm.removeSelectedUserGroup = removeSelectedUserGroup;
vm.selectAll = selectAll;
@@ -216,13 +219,47 @@
}
function getUserFromArrayById(userId, users) {
- var userFound;
- angular.forEach(users, function(user){
- if(userId === user.id) {
- userFound = user;
+ return _.find(users, function(u) { return u.id === userId });
+ }
+
+ function openBulkUserGroupPicker(event) {
+ var firstSelectedUser = getUserFromArrayById(vm.selection[0], vm.users);
+
+ vm.selectedBulkUserGroups = _.clone(firstSelectedUser.userGroups);
+
+ vm.userGroupPicker = {
+ title: "Select user groups",
+ view: "usergrouppicker",
+ selection: vm.selectedBulkUserGroups,
+ closeButtonLabel: "Cancel",
+ show: true,
+ submit: function (model) {
+ usersResource.setUserGroupsOnUsers(model.selection, vm.selection).then(function (data) {
+ // sorting to ensure they show up in right order when updating the UI
+ vm.selectedBulkUserGroups.sort(function (a, b) {
+ return a.alias > b.alias ? 1 : a.alias < b.alias ? -1 : 0;
+ });
+ // apply changes to UI
+ _.each(vm.selection,
+ function(userId) {
+ var user = getUserFromArrayById(userId, vm.users);
+ user.userGroups = vm.selectedBulkUserGroups;
+ });
+ vm.selectedBulkUserGroups = [];
+ vm.userGroupPicker.show = false;
+ vm.userGroupPicker = null;
+ formHelper.showNotifications(data);
+ clearSelection();
+ }, function (error) {
+ formHelper.showNotifications(error.data);
+ });
+ },
+ close: function (oldModel) {
+ vm.selectedBulkUserGroups = [];
+ vm.userGroupPicker.show = false;
+ vm.userGroupPicker = null;
}
- });
- return userFound;
+ };
}
function openUserGroupPicker(event) {
@@ -488,6 +525,8 @@
vm.allowEnableUser = true;
vm.allowSetUserGroup = true;
+ var firstSelectedUserGroups;
+
angular.forEach(users, function (user) {
if (!user.selected) {
@@ -514,6 +553,19 @@
vm.allowEnableUser = false;
}
+ // store the user group aliases of the first selected user
+ if (!firstSelectedUserGroups) {
+ firstSelectedUserGroups = user.userGroups.map(function (ug) { return ug.alias; });
+ vm.allowSetUserGroup = true;
+ } else if (vm.allowSetUserGroup === true) {
+ // for 2nd+ selected user, compare the user group aliases to determine if we should allow bulk editing.
+ // we don't allow bulk editing of users not currently having the same assigned user groups, as we can't
+ // really support that in the user group picker.
+ var userGroups = user.userGroups.map(function(ug) { return ug.alias; });
+ if (_.difference(firstSelectedUserGroups, userGroups).length > 0) {
+ vm.allowSetUserGroup = false;
+ }
+ }
});
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html
index 0293833f76..4490b33e43 100644
--- a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html
+++ b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html
@@ -47,7 +47,7 @@
@@ -60,32 +60,32 @@
-
+
-
+
-
+
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
index 717c27270c..daddfb57ef 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
@@ -1126,6 +1126,17 @@ To manage your website, simply open the Umbraco back office and start adding con
Script view not saved
An error occurred saving the file.
An error occurred saving the file.
+ Deleted %0% user groups
+ %0% was deleted
+ Enabled %0% users
+ An error occurred while enabling the users
+ Disabled %0% users
+ An error occurred while disabling the users
+ %0% is now enabled
+ An error occurred while enabling the user
+ %0% is now disabled
+ An error occurred while disabling the user
+ User groups have been set
Uses CSS syntax ex: h1, .redHeader, .blueTex
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
index 8620a5c75f..2ddb6094b4 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
@@ -1095,17 +1095,17 @@ To manage your website, simply open the Umbraco back office and start adding con
Script view not saved
An error occurred saving the file.
An error occurred saving the file.
-
Enabled %0% users
An error occurred while enabling the users
Disabled %0% users
An error occurred while disabling the users
-
- %0% is now enabled
+ %0% is now enabled
An error occurred while enabling the user
%0% is now disabled
An error occurred while disabling the user
-
+ User groups have been set
+ Deleted %0% user groups
+ %0% was deleted
Uses CSS syntax ex: h1, .redHeader, .blueTex
diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs
index 37d712c362..a2aa8e6b4d 100644
--- a/src/Umbraco.Web/Editors/EntityController.cs
+++ b/src/Umbraco.Web/Editors/EntityController.cs
@@ -19,6 +19,7 @@ using Umbraco.Web.Dynamics;
using System.Text.RegularExpressions;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using System.Web.Http.Controllers;
+using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Xml;
namespace Umbraco.Web.Editors
@@ -541,11 +542,30 @@ namespace Umbraco.Web.Editors
var objectType = ConvertToObjectType(type);
if (objectType.HasValue)
{
+ IEnumerable entities;
long totalRecords;
- //if it's from root, don't return recycled
- var entities = id == Constants.System.Root
- ? Services.EntityService.GetPagedDescendantsFromRoot(objectType.Value, pageNumber - 1, pageSize, out totalRecords, orderBy, orderDirection, filter, includeTrashed:false)
- : Services.EntityService.GetPagedDescendants(id, objectType.Value, pageNumber - 1, pageSize, out totalRecords, orderBy, orderDirection, filter);
+
+ if (id == Constants.System.Root)
+ {
+ int[] aids = null;
+ switch (type)
+ {
+ case UmbracoEntityTypes.Document:
+ aids = Security.CurrentUser.AllStartContentIds;
+ break;
+ case UmbracoEntityTypes.Media:
+ aids = Security.CurrentUser.AllStartMediaIds;
+ break;
+ }
+
+ entities = aids != null && aids.Length > 0
+ ? Services.EntityService.GetPagedDescendants(aids, objectType.Value, pageNumber - 1, pageSize, out totalRecords, orderBy, orderDirection, filter)
+ : Services.EntityService.GetPagedDescendantsFromRoot(objectType.Value, pageNumber - 1, pageSize, out totalRecords, orderBy, orderDirection, filter, includeTrashed: false);
+ }
+ else
+ {
+ entities = Services.EntityService.GetPagedDescendants(id, objectType.Value, pageNumber - 1, pageSize, out totalRecords, orderBy, orderDirection, filter);
+ }
if (totalRecords == 0)
{
@@ -618,9 +638,17 @@ namespace Umbraco.Web.Editors
{
if (startNode > 0)
{
+ // descendants
+ // "__Path: -1*,1234,*" -- the first "*" stands for path-to-1234
sb.Append("__Path: \\-1*\\,");
sb.Append(startNode.ToString(CultureInfo.InvariantCulture));
sb.Append("\\,* ");
+
+ // self
+ // "__Path: -1*,1234" -- the first "*" stands for path-to-1234
+ sb.Append("__Path: \\-1*\\,");
+ sb.Append(startNode.ToString(CultureInfo.InvariantCulture));
+ sb.Append(" ");
}
}
if (startNodes.Length > 0)
@@ -918,6 +946,37 @@ namespace Umbraco.Web.Editors
var ids = Services.EntityService.Get(id).Path.Split(',').Select(int.Parse).Distinct().ToArray();
+ int[] aids = null;
+ switch (entityType)
+ {
+ case UmbracoEntityTypes.Document:
+ aids = Security.CurrentUser.AllStartContentIds;
+ break;
+ case UmbracoEntityTypes.Media:
+ aids = Security.CurrentUser.AllStartMediaIds;
+ break;
+ }
+
+ if (aids != null && aids.Length > 0)
+ {
+ var lids = new List();
+ var ok = false;
+ foreach (var i in ids)
+ {
+ if (ok)
+ {
+ lids.Add(i);
+ continue;
+ }
+ if (aids.Contains(i))
+ {
+ lids.Add(i);
+ ok = true;
+ }
+ }
+ ids = lids.ToArray();
+ }
+
return ids.Length == 0
? Enumerable.Empty()
: Services.EntityService.GetAll(objectType.Value, ids)
diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs
index ed4b1c2f63..1603615a58 100644
--- a/src/Umbraco.Web/Editors/MediaController.cs
+++ b/src/Umbraco.Web/Editors/MediaController.cs
@@ -250,6 +250,13 @@ namespace Umbraco.Web.Editors
}
#region GetChildren
+
+ private int[] _userStartNodes;
+ protected int[] UserStartNodes
+ {
+ get { return _userStartNodes ?? (_userStartNodes = Security.CurrentUser.AllStartMediaIds); }
+ }
+
///
/// Returns the child media objects - using the entity INT id
///
@@ -262,6 +269,25 @@ namespace Umbraco.Web.Editors
bool orderBySystemField = true,
string filter = "")
{
+ //if a request is made for the root node data but the user's start node is not the default, then
+ // we need to return their start nodes
+ if (id == Constants.System.Root && UserStartNodes.Length > 0 && UserStartNodes.Contains(Constants.System.Root) == false)
+ {
+ if (pageNumber > 0)
+ return new PagedResult>(0, 0, 0);
+ var nodes = Services.MediaService.GetByIds(UserStartNodes).ToArray();
+ if (nodes.Length == 0)
+ return new PagedResult>(0, 0, 0);
+ if (pageSize < nodes.Length) pageSize = nodes.Length; // bah
+ var pr = new PagedResult>(nodes.Length, pageNumber, pageSize)
+ {
+ Items = nodes.Select(Mapper.Map>)
+ };
+ return pr;
+ }
+
+ // else proceed as usual
+
long totalChildren;
IMedia[] children;
if (pageNumber > 0 && pageSize > 0)
diff --git a/src/Umbraco.Web/Editors/UserGroupsController.cs b/src/Umbraco.Web/Editors/UserGroupsController.cs
index 43e7810227..7c2b589e97 100644
--- a/src/Umbraco.Web/Editors/UserGroupsController.cs
+++ b/src/Umbraco.Web/Editors/UserGroupsController.cs
@@ -5,7 +5,6 @@ using System.Net;
using System.Net.Http;
using System.Web.Http;
using AutoMapper;
-using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
@@ -87,5 +86,21 @@ namespace Umbraco.Web.Editors
return display;
}
+
+ [HttpPost]
+ [HttpDelete]
+ public HttpResponseMessage PostDeleteUserGroups([FromUri] int[] userGroupIds)
+ {
+ var userGroups = Services.UserService.GetAllUserGroups(userGroupIds).ToArray();
+ foreach (var userGroup in userGroups)
+ {
+ Services.UserService.DeleteUserGroup(userGroup);
+ }
+ if (userGroups.Length > 1)
+ return Request.CreateNotificationSuccessResponse(
+ Services.TextService.Localize("speechBubbles/deleteUserGroupsSuccess", new[] {userGroups.Length.ToString()}));
+ return Request.CreateNotificationSuccessResponse(
+ Services.TextService.Localize("speechBubbles/deleteUserGroupSuccess", new[] {userGroups[0].Name}));
+ }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Editors/UsersController.cs b/src/Umbraco.Web/Editors/UsersController.cs
index 2625568c3e..0039128e86 100644
--- a/src/Umbraco.Web/Editors/UsersController.cs
+++ b/src/Umbraco.Web/Editors/UsersController.cs
@@ -546,6 +546,23 @@ namespace Umbraco.Web.Editors
Services.TextService.Localize("speechBubbles/enableUserSuccess", new[] { users[0].Name }));
}
+ public HttpResponseMessage PostSetUserGroupsOnUsers([FromUri]string[] userGroupAliases, [FromUri]int[] userIds)
+ {
+ var users = Services.UserService.GetUsersById(userIds).ToArray();
+ var userGroups = Services.UserService.GetUserGroupsByAlias(userGroupAliases).Select(x => x.ToReadOnlyGroup()).ToArray();
+ foreach (var u in users)
+ {
+ u.ClearGroups();
+ foreach (var userGroup in userGroups)
+ {
+ u.AddGroup(userGroup);
+ }
+ }
+ Services.UserService.Save(users);
+ return Request.CreateNotificationSuccessResponse(
+ Services.TextService.Localize("speechBubbles/setUserGroupOnUsersSuccess"));
+ }
+
public class PagedUserResult : PagedResult
{
public PagedUserResult(long totalItems, long pageNumber, long pageSize) : base(totalItems, pageNumber, pageSize)
diff --git a/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs
index cd19d36f2d..7034101a83 100644
--- a/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs
+++ b/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs
@@ -46,8 +46,8 @@ namespace Umbraco.Web.Security.Providers
{
base.Initialize(name, config);
- // test for membertype (if not specified, choose the first member type available)
- // We'll support both names for legacy reasons: defaultUserTypeAlias & defaultUserGroupAlias
+ // test for membertype (if not specified, choose the first member type available)
+ // We'll support both names for legacy reasons: defaultUserTypeAlias & defaultUserGroupAlias
if (config["defaultUserTypeAlias"] != null)
{
diff --git a/src/umbraco.providers/members/UmbracoMembershipProvider.cs b/src/umbraco.providers/members/UmbracoMembershipProvider.cs
index 2a563d27ce..648bf5a0d5 100644
--- a/src/umbraco.providers/members/UmbracoMembershipProvider.cs
+++ b/src/umbraco.providers/members/UmbracoMembershipProvider.cs
@@ -126,7 +126,7 @@ namespace umbraco.providers.members
_defaultMemberTypeAlias = config["defaultMemberTypeAlias"];
if (_defaultMemberTypeAlias.IsNullOrWhiteSpace())
{
- throw new ProviderException("No default user group alias is specified in the web.config string. Please add a 'defaultUserTypeAlias' to the add element in the provider declaration in web.config");
+ throw new ProviderException("No default MemberType alias is specified in the web.config string. Please add a 'defaultMemberTypeAlias' to the add element in the provider declaration in web.config");
}
_hasDefaultMember = true;
}