Merge pull request #2122 from umbraco/temp-U4-10243
U4-10243 Umbraco 7.7. Difference between "Enable/Disable" and "LockedOut"
This commit is contained in:
@@ -545,6 +545,9 @@ namespace Umbraco.Core.Security
|
||||
/// </summary>
|
||||
/// <param name="user"/><param name="lockoutEnd"/>
|
||||
/// <returns/>
|
||||
/// <remarks>
|
||||
/// Currently we do not suport a timed lock out, when they are locked out, an admin will have to reset the status
|
||||
/// </remarks>
|
||||
public Task SetLockoutEndDateAsync(BackOfficeIdentityUser user, DateTimeOffset lockoutEnd)
|
||||
{
|
||||
if (user == null) throw new ArgumentNullException("user");
|
||||
|
||||
@@ -4,13 +4,33 @@
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Used by the users section to get users and send requests to create, invite, delete, etc. users.
|
||||
* Used by the users section to get users and send requests to create, invite, disable, etc. users.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function usersResource($http, umbRequestHelper, $q, umbDataFormatter) {
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.usersResource#clearAvatar
|
||||
* @methodOf umbraco.resources.usersResource
|
||||
*
|
||||
* @description
|
||||
* Deletes the user avatar
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* usersResource.clearAvatar(1)
|
||||
* .then(function() {
|
||||
* alert("avatar is gone");
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Array} id id of user.
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
function clearAvatar(userId) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
@@ -22,6 +42,26 @@
|
||||
'Failed to clear the user avatar ' + userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.usersResource#disableUsers
|
||||
* @methodOf umbraco.resources.usersResource
|
||||
*
|
||||
* @description
|
||||
* Disables a collection of users
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* usersResource.disableUsers([1, 2, 3, 4, 5])
|
||||
* .then(function() {
|
||||
* alert("users were disabled");
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Array} ids ids of users to disable.
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
function disableUsers(userIds) {
|
||||
if (!userIds) {
|
||||
throw "userIds not specified";
|
||||
@@ -39,6 +79,26 @@
|
||||
'Failed to disable the users ' + userIds.join(","));
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.usersResource#enableUsers
|
||||
* @methodOf umbraco.resources.usersResource
|
||||
*
|
||||
* @description
|
||||
* Enables a collection of users
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* usersResource.enableUsers([1, 2, 3, 4, 5])
|
||||
* .then(function() {
|
||||
* alert("users were enabled");
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Array} ids ids of users to enable.
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
function enableUsers(userIds) {
|
||||
if (!userIds) {
|
||||
throw "userIds not specified";
|
||||
@@ -55,6 +115,63 @@
|
||||
'Failed to enable the users ' + userIds.join(","));
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.usersResource#unlockUsers
|
||||
* @methodOf umbraco.resources.usersResource
|
||||
*
|
||||
* @description
|
||||
* Unlocks a collection of users
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* usersResource.unlockUsers([1, 2, 3, 4, 5])
|
||||
* .then(function() {
|
||||
* alert("users were unlocked");
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Array} ids ids of users to unlock.
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
function unlockUsers(userIds) {
|
||||
if (!userIds) {
|
||||
throw "userIds not specified";
|
||||
}
|
||||
|
||||
//we need to create a custom query string for the usergroup array, so create it now and we can append the user groups if needed
|
||||
var qry = "userIds=" + userIds.join("&userIds=");
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"userApiBaseUrl",
|
||||
"PostUnlockUsers", qry)),
|
||||
'Failed to enable the users ' + userIds.join(","));
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.usersResource#setUserGroupsOnUsers
|
||||
* @methodOf umbraco.resources.usersResource
|
||||
*
|
||||
* @description
|
||||
* Overwrites the existing user groups on a collection of users
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* usersResource.setUserGroupsOnUsers(['admin', 'editor'], [1, 2, 3, 4, 5])
|
||||
* .then(function() {
|
||||
* alert("users were updated");
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Array} userGroupAliases aliases of user groups.
|
||||
* @param {Array} ids ids of users to update.
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
function setUserGroupsOnUsers(userGroups, userIds) {
|
||||
var userGroupAliases = userGroups.map(function(o) { return o.alias; });
|
||||
var query = "userGroupAliases=" + userGroupAliases.join("&userGroupAliases=") + "&userIds=" + userIds.join("&userIds=");
|
||||
@@ -67,6 +184,34 @@
|
||||
'Failed to set user groups ' + userGroupAliases.join(",") + ' on the users ' + userIds.join(","));
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.usersResource#getPagedResults
|
||||
* @methodOf umbraco.resources.usersResource
|
||||
*
|
||||
* @description
|
||||
* Get users
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* usersResource.getPagedResults({pageSize: 10, pageNumber: 2})
|
||||
* .then(function(data) {
|
||||
* var users = data.items;
|
||||
* alert('they are here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Object} options optional options object
|
||||
* @param {Int} options.pageSize if paging data, number of users per page, default = 25
|
||||
* @param {Int} options.pageNumber if paging data, current page index, default = 1
|
||||
* @param {String} options.filter if provided, query will only return those with names matching the filter
|
||||
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending`
|
||||
* @param {String} options.orderBy property to order users by, default: `Username`
|
||||
* @param {Array} options.userGroups property to filter users by user group
|
||||
* @param {Array} options.userStates property to filter users by user state
|
||||
* @returns {Promise} resourcePromise object containing an array of content items.
|
||||
*
|
||||
*/
|
||||
function getPagedResults(options) {
|
||||
var defaults = {
|
||||
pageSize: 25,
|
||||
@@ -119,6 +264,26 @@
|
||||
'Failed to retrieve users paged result');
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.usersResource#getUser
|
||||
* @methodOf umbraco.resources.usersResource
|
||||
*
|
||||
* @description
|
||||
* Gets a user
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* usersResource.getUser(1)
|
||||
* .then(function(user) {
|
||||
* alert("It's here");
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Array} id user id.
|
||||
* @returns {Promise} resourcePromise object containing the user.
|
||||
*
|
||||
*/
|
||||
function getUser(userId) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
@@ -130,6 +295,26 @@
|
||||
"Failed to retrieve data for user " + userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.usersResource#createUser
|
||||
* @methodOf umbraco.resources.usersResource
|
||||
*
|
||||
* @description
|
||||
* Creates a new user
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* usersResource.createUser(user)
|
||||
* .then(function(newUser) {
|
||||
* alert("It's here");
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Object} user user to create
|
||||
* @returns {Promise} resourcePromise object containing the new user.
|
||||
*
|
||||
*/
|
||||
function createUser(user) {
|
||||
if (!user) {
|
||||
throw "user not specified";
|
||||
@@ -147,6 +332,26 @@
|
||||
"Failed to save user");
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.usersResource#inviteUser
|
||||
* @methodOf umbraco.resources.usersResource
|
||||
*
|
||||
* @description
|
||||
* Creates and sends an email invitation to a new user
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* usersResource.inviteUser(user)
|
||||
* .then(function(newUser) {
|
||||
* alert("It's here");
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Object} user user to invite
|
||||
* @returns {Promise} resourcePromise object containing the new user.
|
||||
*
|
||||
*/
|
||||
function inviteUser(user) {
|
||||
if (!user) {
|
||||
throw "user not specified";
|
||||
@@ -164,6 +369,26 @@
|
||||
"Failed to invite user");
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.usersResource#saveUser
|
||||
* @methodOf umbraco.resources.usersResource
|
||||
*
|
||||
* @description
|
||||
* Saves a user
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* usersResource.saveUser(user)
|
||||
* .then(function(updatedUser) {
|
||||
* alert("It's here");
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Object} user object to save
|
||||
* @returns {Promise} resourcePromise object containing the updated user.
|
||||
*
|
||||
*/
|
||||
function saveUser(user) {
|
||||
if (!user) {
|
||||
throw "user not specified";
|
||||
@@ -185,6 +410,7 @@
|
||||
var resource = {
|
||||
disableUsers: disableUsers,
|
||||
enableUsers: enableUsers,
|
||||
unlockUsers: unlockUsers,
|
||||
setUserGroupsOnUsers: setUserGroupsOnUsers,
|
||||
getPagedResults: getPagedResults,
|
||||
getUser: getUser,
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
// Colors
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
vm.removeSelectedItem = removeSelectedItem;
|
||||
vm.disableUser = disableUser;
|
||||
vm.enableUser = enableUser;
|
||||
vm.unlockUser = unlockUser;
|
||||
vm.clearAvatar = clearAvatar;
|
||||
vm.save = save;
|
||||
vm.toggleChangePassword = toggleChangePassword;
|
||||
@@ -254,11 +255,11 @@
|
||||
function disableUser() {
|
||||
vm.disableUserButtonState = "busy";
|
||||
usersResource.disableUsers([vm.user.id]).then(function (data) {
|
||||
vm.user.userState = 1;
|
||||
setUserDisplayState();
|
||||
vm.disableUserButtonState = "success";
|
||||
formHelper.showNotifications(data);
|
||||
}, function(error){
|
||||
vm.user.userState = 1;
|
||||
setUserDisplayState();
|
||||
vm.disableUserButtonState = "success";
|
||||
formHelper.showNotifications(data);
|
||||
}, function (error) {
|
||||
vm.disableUserButtonState = "error";
|
||||
formHelper.showNotifications(error.data);
|
||||
});
|
||||
@@ -267,16 +268,28 @@
|
||||
function enableUser() {
|
||||
vm.enableUserButtonState = "busy";
|
||||
usersResource.enableUsers([vm.user.id]).then(function (data) {
|
||||
vm.user.userState = 0;
|
||||
setUserDisplayState();
|
||||
vm.enableUserButtonState = "success";
|
||||
formHelper.showNotifications(data);
|
||||
}, function(error){
|
||||
vm.disableUserButtonState = "error";
|
||||
vm.user.userState = 0;
|
||||
setUserDisplayState();
|
||||
vm.enableUserButtonState = "success";
|
||||
formHelper.showNotifications(data);
|
||||
}, function (error) {
|
||||
vm.enableUserButtonState = "error";
|
||||
formHelper.showNotifications(error.data);
|
||||
});
|
||||
}
|
||||
|
||||
function unlockUser() {
|
||||
vm.unlockUserButtonState = "busy";
|
||||
usersResource.unlockUsers([vm.user.id]).then(function (data) {
|
||||
vm.user.userState = 0;
|
||||
setUserDisplayState();
|
||||
vm.unlockUserButtonState = "success";
|
||||
formHelper.showNotifications(data);
|
||||
}, function (error) {
|
||||
vm.unlockUserButtonState = "error";
|
||||
formHelper.showNotifications(error.data);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function clearAvatar() {
|
||||
// get user
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<div ng-controller="Umbraco.Editors.Users.UserController as vm" class="clearfix">
|
||||
|
||||
<umb-load-indicator ng-show="vm.loading"></umb-load-indicator>
|
||||
<umb-load-indicator
|
||||
ng-if="vm.loading">
|
||||
</umb-load-indicator>
|
||||
|
||||
<form name="editUserForm" novalidate val-form-manager>
|
||||
|
||||
@@ -234,29 +236,43 @@
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<div style="margin-bottom: 10px;">
|
||||
<umb-button
|
||||
ng-if="vm.user.userDisplayState.key === 'Active' && !vm.user.isCurrentUser"
|
||||
type="button"
|
||||
button-style="[danger,block]"
|
||||
action="vm.disableUser()"
|
||||
state="vm.disableUserButtonState"
|
||||
label="Disable"
|
||||
label-key="actions_disable"
|
||||
size="m">
|
||||
</umb-button>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 10px;">
|
||||
<umb-button
|
||||
ng-if="vm.user.userDisplayState.key === 'Disabled' && !vm.user.isCurrentUser || vm.user.userDisplayState.key === 'LockedOut' && !vm.user.isCurrentUser"
|
||||
ng-if="vm.user.userDisplayState.key === 'Disabled' && !vm.user.isCurrentUser"
|
||||
type="button"
|
||||
button-style="[success,block]"
|
||||
state="vm.enableUserButtonState"
|
||||
action="vm.enableUser()"
|
||||
label="Enable"
|
||||
label-key="actions_enable"
|
||||
size="m">
|
||||
size="s">
|
||||
</umb-button>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 10px;">
|
||||
<umb-button
|
||||
ng-if="vm.user.userDisplayState.key === 'LockedOut' && !vm.user.isCurrentUser"
|
||||
type="button"
|
||||
button-style="[success,block]"
|
||||
state="vm.unlockUserButtonState"
|
||||
action="vm.unlockUser()"
|
||||
label="Unlock"
|
||||
label-key="actions_unlock"
|
||||
size="s">
|
||||
</umb-button>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 10px;">
|
||||
<umb-button
|
||||
ng-if="vm.user.userDisplayState.key !== 'Disabled' && !vm.user.isCurrentUser"
|
||||
type="button"
|
||||
button-style="[info,block]"
|
||||
action="vm.disableUser()"
|
||||
state="vm.disableUserButtonState"
|
||||
label="Disable"
|
||||
label-key="actions_disable"
|
||||
size="s">
|
||||
</umb-button>
|
||||
</div>
|
||||
|
||||
@@ -268,7 +284,7 @@
|
||||
label-key="general_changePassword"
|
||||
state="changePasswordButtonState"
|
||||
ng-if="vm.changePasswordModel.isChanging === false"
|
||||
size="m">
|
||||
size="s">
|
||||
</umb-button>
|
||||
|
||||
<ng-form ng-if="vm.changePasswordModel.isChanging" name="passwordForm" class="block-form" val-form-manager>
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
vm.allowDisableUser = true;
|
||||
vm.allowEnableUser = true;
|
||||
vm.allowUnlockUser = true;
|
||||
vm.allowSetUserGroup = true;
|
||||
|
||||
vm.layouts = [
|
||||
@@ -76,6 +77,7 @@
|
||||
vm.clickUser = clickUser;
|
||||
vm.disableUsers = disableUsers;
|
||||
vm.enableUsers = enableUsers;
|
||||
vm.unlockUsers = unlockUsers;
|
||||
vm.openBulkUserGroupPicker = openBulkUserGroupPicker;
|
||||
vm.openUserGroupPicker = openUserGroupPicker;
|
||||
vm.removeSelectedUserGroup = removeSelectedUserGroup;
|
||||
@@ -241,6 +243,28 @@
|
||||
});
|
||||
}
|
||||
|
||||
function unlockUsers() {
|
||||
vm.unlockUserButtonState = "busy";
|
||||
usersResource.unlockUsers(vm.selection).then(function (data) {
|
||||
// update userState
|
||||
angular.forEach(vm.selection, function (userId) {
|
||||
var user = getUserFromArrayById(userId, vm.users);
|
||||
if (user) {
|
||||
user.userState = 0;
|
||||
}
|
||||
});
|
||||
// show the correct badges
|
||||
setUserDisplayState(vm.users);
|
||||
// show notification
|
||||
formHelper.showNotifications(data);
|
||||
vm.unlockUserButtonState = "init";
|
||||
clearSelection();
|
||||
}, function (error) {
|
||||
vm.unlockUserButtonState = "error";
|
||||
formHelper.showNotifications(error.data);
|
||||
});
|
||||
}
|
||||
|
||||
function getUserFromArrayById(userId, users) {
|
||||
return _.find(users, function (u) { return u.id === userId });
|
||||
}
|
||||
@@ -560,6 +584,7 @@
|
||||
// reset all states
|
||||
vm.allowDisableUser = true;
|
||||
vm.allowEnableUser = true;
|
||||
vm.allowUnlockUser = true;
|
||||
vm.allowSetUserGroup = true;
|
||||
|
||||
var firstSelectedUserGroups;
|
||||
@@ -574,6 +599,7 @@
|
||||
if (user.isCurrentUser) {
|
||||
vm.allowDisableUser = false;
|
||||
vm.allowEnableUser = false;
|
||||
vm.allowUnlockUser = false;
|
||||
vm.allowSetUserGroup = false;
|
||||
return;
|
||||
}
|
||||
@@ -590,6 +616,14 @@
|
||||
vm.allowEnableUser = false;
|
||||
}
|
||||
|
||||
if (user.userDisplayState && user.userDisplayState.key === "LockedOut") {
|
||||
vm.allowEnableUser = false;
|
||||
}
|
||||
|
||||
if (user.userDisplayState && user.userDisplayState.key !== "LockedOut") {
|
||||
vm.allowUnlockUser = false;
|
||||
}
|
||||
|
||||
// store the user group aliases of the first selected user
|
||||
if (!firstSelectedUserGroups) {
|
||||
firstSelectedUserGroups = user.userGroups.map(function (ug) { return ug.alias; });
|
||||
|
||||
@@ -81,6 +81,17 @@
|
||||
action="vm.enableUsers()">
|
||||
</umb-button>
|
||||
</div>
|
||||
<div style="margin-right: 5px;">
|
||||
<umb-button
|
||||
ng-if="vm.allowUnlockUser"
|
||||
type="button"
|
||||
size="xs"
|
||||
state="vm.unlockUserButtonState"
|
||||
label-key="actions_unlock"
|
||||
icon="icon-unlocked"
|
||||
action="vm.unlockUsers()">
|
||||
</umb-button>
|
||||
</div>
|
||||
<div>
|
||||
<umb-button
|
||||
ng-if="vm.allowDisableUser"
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
<key alias="translate">Translate</key>
|
||||
<key alias="update">Update</key>
|
||||
<key alias="setPermissions">Set permissions</key>
|
||||
<key alias="unlock">Unlock</key>
|
||||
</area>
|
||||
<area alias="actionCategories">
|
||||
<key alias="content">Content</key>
|
||||
@@ -1216,6 +1217,10 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="setUserGroupOnUsersSuccess">User groups have been set</key>
|
||||
<key alias="deleteUserGroupsSuccess">Deleted %0% user groups</key>
|
||||
<key alias="deleteUserGroupSuccess">%0% was deleted</key>
|
||||
<key alias="unlockUsersSuccess">Unlocked %0% users</key>
|
||||
<key alias="unlockUsersError">An error occurred while unlocking the users</key>
|
||||
<key alias="unlockUserSuccess">%0% is now unlocked</key>
|
||||
<key alias="unlockUserError">An error occurred while unlocking the user</key>
|
||||
</area>
|
||||
<area alias="stylesheet">
|
||||
<key alias="aliasHelp">Uses CSS syntax ex: h1, .redHeader, .blueTex</key>
|
||||
|
||||
@@ -557,6 +557,42 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
return Request.CreateNotificationSuccessResponse(
|
||||
Services.TextService.Localize("speechBubbles/enableUserSuccess", new[] { users[0].Name }));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks the users with the given user ids
|
||||
/// </summary>
|
||||
/// <param name="userIds"></param>
|
||||
public async Task<HttpResponseMessage> PostUnlockUsers([FromUri]int[] userIds)
|
||||
{
|
||||
if (userIds.Length <= 0)
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
|
||||
if (userIds.Length == 1)
|
||||
{
|
||||
var unlockResult = await UserManager.SetLockoutEndDateAsync(userIds[0], DateTimeOffset.Now);
|
||||
if (unlockResult.Succeeded == false)
|
||||
{
|
||||
return Request.CreateValidationErrorResponse(
|
||||
string.Format("Could not unlock for user {0} - error {1}", userIds[0], unlockResult.Errors.First()));
|
||||
}
|
||||
var user = await UserManager.FindByIdAsync(userIds[0]);
|
||||
return Request.CreateNotificationSuccessResponse(
|
||||
Services.TextService.Localize("speechBubbles/unlockUserSuccess", new[] { user.Name }));
|
||||
}
|
||||
|
||||
foreach (var u in userIds)
|
||||
{
|
||||
var unlockResult = await UserManager.SetLockoutEndDateAsync(u, DateTimeOffset.Now);
|
||||
if (unlockResult.Succeeded == false)
|
||||
{
|
||||
return Request.CreateValidationErrorResponse(
|
||||
string.Format("Could not unlock for user {0} - error {1}", u, unlockResult.Errors.First()));
|
||||
}
|
||||
}
|
||||
|
||||
return Request.CreateNotificationSuccessResponse(
|
||||
Services.TextService.Localize("speechBubbles/unlockUsersSuccess", new[] { userIds.Length.ToString() }));
|
||||
}
|
||||
|
||||
public HttpResponseMessage PostSetUserGroupsOnUsers([FromUri]string[] userGroupAliases, [FromUri]int[] userIds)
|
||||
|
||||
Reference in New Issue
Block a user