mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
GUACAMOLE-926: Grant permissions to all users / groups.
This commit is contained in:
@@ -17,6 +17,8 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* global _ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The controller for the connection import page.
|
* The controller for the connection import page.
|
||||||
*/
|
*/
|
||||||
@@ -24,14 +26,21 @@ angular.module('import').controller('importConnectionsController', ['$scope', '$
|
|||||||
function importConnectionsController($scope, $injector) {
|
function importConnectionsController($scope, $injector) {
|
||||||
|
|
||||||
// Required services
|
// Required services
|
||||||
|
const $q = $injector.get('$q');
|
||||||
const $routeParams = $injector.get('$routeParams');
|
const $routeParams = $injector.get('$routeParams');
|
||||||
const connectionParseService = $injector.get('connectionParseService');
|
const connectionParseService = $injector.get('connectionParseService');
|
||||||
const connectionService = $injector.get('connectionService');
|
const connectionService = $injector.get('connectionService');
|
||||||
|
const permissionService = $injector.get('permissionService');
|
||||||
|
const userService = $injector.get('userService');
|
||||||
|
const userGroupService = $injector.get('userGroupService');
|
||||||
|
|
||||||
// Required types
|
// Required types
|
||||||
const DirectoryPatch = $injector.get('DirectoryPatch');
|
const DirectoryPatch = $injector.get('DirectoryPatch');
|
||||||
const ParseError = $injector.get('ParseError');
|
const ParseError = $injector.get('ParseError');
|
||||||
|
const PermissionSet = $injector.get('PermissionSet');
|
||||||
const TranslatableMessage = $injector.get('TranslatableMessage');
|
const TranslatableMessage = $injector.get('TranslatableMessage');
|
||||||
|
const User = $injector.get('User');
|
||||||
|
const UserGroup = $injector.get('UserGroup');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a successful response to an import PATCH request, make another
|
* Given a successful response to an import PATCH request, make another
|
||||||
@@ -56,10 +65,133 @@ angular.module('import').controller('importConnectionsController', ['$scope', '$
|
|||||||
|
|
||||||
.then(deletionResponse =>
|
.then(deletionResponse =>
|
||||||
console.log("Deletion response", deletionResponse))
|
console.log("Deletion response", deletionResponse))
|
||||||
.catch(handleParseError);
|
.catch(handleError);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create all users and user groups mentioned in the import file that don't
|
||||||
|
* already exist in the current data source.
|
||||||
|
*
|
||||||
|
* @param {ParseResult} parseResult
|
||||||
|
* The result of parsing the user-supplied import file.
|
||||||
|
*
|
||||||
|
* @return {Object}
|
||||||
|
* An object containing the results of the calls to create the users
|
||||||
|
* and groups.
|
||||||
|
*/
|
||||||
|
function createUsersAndGroups(parseResult) {
|
||||||
|
|
||||||
|
const dataSource = $routeParams.dataSource;
|
||||||
|
|
||||||
|
return $q.all({
|
||||||
|
existingUsers : userService.getUsers(dataSource),
|
||||||
|
existingGroups : userGroupService.getUserGroups(dataSource)
|
||||||
|
}).then(({existingUsers, existingGroups}) => {
|
||||||
|
|
||||||
|
const userPatches = Object.keys(parseResult.users)
|
||||||
|
|
||||||
|
// Filter out any existing users
|
||||||
|
.filter(identifier => !existingUsers[identifier])
|
||||||
|
|
||||||
|
// A patch to create each new user
|
||||||
|
.map(username => new DirectoryPatch({
|
||||||
|
op: 'add',
|
||||||
|
path: '/',
|
||||||
|
value: new User({ username })
|
||||||
|
}));
|
||||||
|
|
||||||
|
const groupPatches = Object.keys(parseResult.groups)
|
||||||
|
|
||||||
|
// Filter out any existing groups
|
||||||
|
.filter(identifier => !existingGroups[identifier])
|
||||||
|
|
||||||
|
// A patch to create each new user group
|
||||||
|
.map(identifier => new DirectoryPatch({
|
||||||
|
op: 'add',
|
||||||
|
path: '/',
|
||||||
|
value: new UserGroup({ identifier })
|
||||||
|
}));
|
||||||
|
|
||||||
|
return $q.all({
|
||||||
|
createdUsers: userService.patchUsers(dataSource, userPatches),
|
||||||
|
createdGroups: userGroupService.patchUserGroups(dataSource, groupPatches)
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grant read permissions for each user and group in the supplied parse
|
||||||
|
* result to each connection in their connection list. Note that there will
|
||||||
|
* be a seperate request for each user and group.
|
||||||
|
*
|
||||||
|
* @param {ParseResult} parseResult
|
||||||
|
* The result of successfully parsing a user-supplied import file.
|
||||||
|
*
|
||||||
|
* @param {Object} response
|
||||||
|
* The response from the PATCH API request.
|
||||||
|
*
|
||||||
|
* @returns {Promise.<Object>}
|
||||||
|
* A promise that will resolve with the result of every permission
|
||||||
|
* granting request.
|
||||||
|
*/
|
||||||
|
function grantConnectionPermissions(parseResult, response) {
|
||||||
|
|
||||||
|
const dataSource = $routeParams.dataSource;
|
||||||
|
|
||||||
|
// All connection grant requests, one per user/group
|
||||||
|
const userRequests = {};
|
||||||
|
const groupRequests = {};
|
||||||
|
|
||||||
|
// Create a PermissionSet granting access to all connections at
|
||||||
|
// the provided indices within the provided parse result
|
||||||
|
const createPermissionSet = indices =>
|
||||||
|
new PermissionSet({ connectionPermissions: indices.reduce(
|
||||||
|
(permissions, index) => {
|
||||||
|
const connectionId = response.patches[index].identifier;
|
||||||
|
permissions[connectionId] = [
|
||||||
|
PermissionSet.ObjectPermissionType.READ];
|
||||||
|
return permissions;
|
||||||
|
}, {}) });
|
||||||
|
|
||||||
|
// Now that we've created all the users, grant access to each
|
||||||
|
_.forEach(parseResult.users, (connectionIndices, identifier) =>
|
||||||
|
|
||||||
|
// Grant the permissions - note the group flag is `false`
|
||||||
|
userRequests[identifier] = permissionService.patchPermissions(
|
||||||
|
dataSource, identifier,
|
||||||
|
|
||||||
|
// Create the permissions to these connections for this user
|
||||||
|
createPermissionSet(connectionIndices),
|
||||||
|
|
||||||
|
// Do not remove any permissions
|
||||||
|
new PermissionSet(),
|
||||||
|
|
||||||
|
// This call is not for a group
|
||||||
|
false));
|
||||||
|
|
||||||
|
// Now that we've created all the groups, grant access to each
|
||||||
|
_.forEach(parseResult.groups, (connectionIndices, identifier) =>
|
||||||
|
|
||||||
|
// Grant the permissions - note the group flag is `true`
|
||||||
|
groupRequests[identifier] = permissionService.patchPermissions(
|
||||||
|
dataSource, identifier,
|
||||||
|
|
||||||
|
// Create the permissions to these connections for this user
|
||||||
|
createPermissionSet(connectionIndices),
|
||||||
|
|
||||||
|
// Do not remove any permissions
|
||||||
|
new PermissionSet(),
|
||||||
|
|
||||||
|
// This call is for a group
|
||||||
|
true));
|
||||||
|
|
||||||
|
// Return the result from all the permission granting calls
|
||||||
|
return $q.all({ ...userRequests, ...groupRequests });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a successfully parsed import file, creating any specified
|
* Process a successfully parsed import file, creating any specified
|
||||||
* connections, creating and granting permissions to any specified users
|
* connections, creating and granting permissions to any specified users
|
||||||
@@ -78,19 +210,32 @@ angular.module('import').controller('importConnectionsController', ['$scope', '$
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function handleParseSuccess(parseResult) {
|
function handleParseSuccess(parseResult) {
|
||||||
connectionService.patchConnections(
|
|
||||||
$routeParams.dataSource, parseResult.patches)
|
|
||||||
|
|
||||||
.then(response => {
|
|
||||||
console.log("Creation Response", response);
|
|
||||||
|
|
||||||
// TODON'T: Delete connections so we can test over and over
|
const dataSource = $routeParams.dataSource;
|
||||||
cleanUpConnections(response);
|
|
||||||
|
console.log("parseResult", parseResult);
|
||||||
|
|
||||||
|
// First, attempt to create the connections
|
||||||
|
connectionService.patchConnections(dataSource, parseResult.patches)
|
||||||
|
.then(response => {
|
||||||
|
|
||||||
|
// If connection creation is successful, create users and groups
|
||||||
|
createUsersAndGroups(parseResult).then(() => {
|
||||||
|
|
||||||
|
grantConnectionPermissions(parseResult, response).then(results => {
|
||||||
|
console.log("permission requests", results);
|
||||||
|
|
||||||
|
// TODON'T: Delete connections so we can test over and over
|
||||||
|
cleanUpConnections(response);
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set any caught error message to the scope for display
|
// Set any caught error message to the scope for display
|
||||||
const handleParseError = error => {
|
const handleError = error => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
$scope.error = error;
|
$scope.error = error;
|
||||||
}
|
}
|
||||||
@@ -150,7 +295,7 @@ angular.module('import').controller('importConnectionsController', ['$scope', '$
|
|||||||
.then(handleParseSuccess)
|
.then(handleParseSuccess)
|
||||||
|
|
||||||
// Display any error found while parsing the file
|
// Display any error found while parsing the file
|
||||||
.catch(handleParseError);
|
.catch(handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.upload = function() {
|
$scope.upload = function() {
|
||||||
|
@@ -199,9 +199,9 @@ angular.module('import').factory('connectionParseService',
|
|||||||
}
|
}
|
||||||
|
|
||||||
return getGroupTransformer().then(groupTransformer =>
|
return getGroupTransformer().then(groupTransformer =>
|
||||||
connectionData.reduce((parseResult, data) => {
|
connectionData.reduce((parseResult, data, index) => {
|
||||||
|
|
||||||
const { patches, users, groups, allUsers, allGroups } = parseResult;
|
const { patches, users, groups } = parseResult;
|
||||||
|
|
||||||
// Run the array data through each provided transform
|
// Run the array data through each provided transform
|
||||||
let connectionObject = data;
|
let connectionObject = data;
|
||||||
@@ -223,15 +223,33 @@ angular.module('import').factory('connectionParseService',
|
|||||||
connectionErrors.push(error);
|
connectionErrors.push(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the user and group identifiers for this connection
|
// The users and user groups that should be granted access
|
||||||
const connectionUsers = connectionObject.users || [];
|
const connectionUsers = connectionObject.users || [];
|
||||||
const connectionGroups = connectionObject.groups || [];
|
const connectionGroups = connectionObject.groups || [];
|
||||||
users.push(connectionUsers);
|
|
||||||
groups.push(connectionGroups);
|
|
||||||
|
|
||||||
// Add all user and user group identifiers to the overall sets
|
// Add this connection index to the list for each user
|
||||||
connectionUsers.forEach(identifier => allUsers[identifier] = true);
|
connectionUsers.forEach(identifier => {
|
||||||
connectionGroups.forEach(identifier => allGroups[identifier] = true);
|
|
||||||
|
// If there's an existing list, add the index to that
|
||||||
|
if (users[identifier])
|
||||||
|
users[identifier].push(index);
|
||||||
|
|
||||||
|
// Otherwise, create a new list with just this index
|
||||||
|
else
|
||||||
|
users[identifier] = [index];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add this connection index to the list for each group
|
||||||
|
connectionGroups.forEach(identifier => {
|
||||||
|
|
||||||
|
// If there's an existing list, add the index to that
|
||||||
|
if (groups[identifier])
|
||||||
|
groups[identifier].push(index);
|
||||||
|
|
||||||
|
// Otherwise, create a new list with just this index
|
||||||
|
else
|
||||||
|
groups[identifier] = [index];
|
||||||
|
});
|
||||||
|
|
||||||
// Translate to a full-fledged Connection
|
// Translate to a full-fledged Connection
|
||||||
const connection = new Connection(connectionObject);
|
const connection = new Connection(connectionObject);
|
||||||
|
@@ -48,28 +48,13 @@ angular.module('import').factory('ParseResult', [function defineParseResult() {
|
|||||||
this.patches = template.patches || [];
|
this.patches = template.patches || [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of user identifiers that should be granted read access to the
|
* An object whose keys are the user identifiers of users specified
|
||||||
* the corresponding connection (at the same array index).
|
* in the batch import. and the keys are an array of indices of
|
||||||
|
* connections to which those users should be granted access.
|
||||||
*
|
*
|
||||||
* @type {String[]}
|
* @type {Object.<String, Integer[]>}
|
||||||
*/
|
*/
|
||||||
this.users = template.users || [];
|
this.users = template.users || {};
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of user group identifiers that should be granted read access
|
|
||||||
* to the corresponding connection (at the same array index).
|
|
||||||
*
|
|
||||||
* @type {String[]}
|
|
||||||
*/
|
|
||||||
this.groups = template.groups || [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An object whose keys are the user identifiers of every user specified
|
|
||||||
* in the batch import. i.e. a set of all user identifiers.
|
|
||||||
*
|
|
||||||
* @type {Object.<String, Boolean>}
|
|
||||||
*/
|
|
||||||
this.allUsers = template.allUsers || {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object whose keys are the user group identifiers of every user
|
* An object whose keys are the user group identifiers of every user
|
||||||
@@ -78,7 +63,7 @@ angular.module('import').factory('ParseResult', [function defineParseResult() {
|
|||||||
*
|
*
|
||||||
* @type {Object.<String, Boolean>}
|
* @type {Object.<String, Boolean>}
|
||||||
*/
|
*/
|
||||||
this.allGroups = template.allGroups || {};
|
this.groups = template.users || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array of errors encountered while parsing the corresponding
|
* An array of errors encountered while parsing the corresponding
|
||||||
|
@@ -190,6 +190,39 @@ angular.module('rest').factory('userGroupService', ['$injector',
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes a request to the REST API to apply a supplied list of user group
|
||||||
|
* patches, returning a promise that can be used for processing the results
|
||||||
|
* of the call.
|
||||||
|
*
|
||||||
|
* This operation is atomic - if any errors are encountered during the
|
||||||
|
* connection patching process, the entire request will fail, and no
|
||||||
|
* changes will be persisted.
|
||||||
|
*
|
||||||
|
* @param {DirectoryPatch.<UserGroup>[]} patches
|
||||||
|
* An array of patches to apply.
|
||||||
|
*
|
||||||
|
* @returns {Promise}
|
||||||
|
* A promise for the HTTP call which will succeed if and only if the
|
||||||
|
* patch operation is successful.
|
||||||
|
*/
|
||||||
|
service.patchUserGroups = function patchUserGroups(dataSource, patches) {
|
||||||
|
|
||||||
|
// Make the PATCH request
|
||||||
|
return authenticationService.request({
|
||||||
|
method : 'PATCH',
|
||||||
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/userGroups',
|
||||||
|
data : patches
|
||||||
|
})
|
||||||
|
|
||||||
|
// Clear the cache
|
||||||
|
.then(function userGroupsPatched(patchResponse){
|
||||||
|
cacheService.users.removeAll();
|
||||||
|
return patchResponse;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return service;
|
return service;
|
||||||
|
|
||||||
}]);
|
}]);
|
||||||
|
@@ -235,6 +235,39 @@ angular.module('rest').factory('userService', ['$injector',
|
|||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes a request to the REST API to apply a supplied list of user patches,
|
||||||
|
* returning a promise that can be used for processing the results of the
|
||||||
|
* call.
|
||||||
|
*
|
||||||
|
* This operation is atomic - if any errors are encountered during the
|
||||||
|
* connection patching process, the entire request will fail, and no
|
||||||
|
* changes will be persisted.
|
||||||
|
*
|
||||||
|
* @param {DirectoryPatch.<User>[]} patches
|
||||||
|
* An array of patches to apply.
|
||||||
|
*
|
||||||
|
* @returns {Promise}
|
||||||
|
* A promise for the HTTP call which will succeed if and only if the
|
||||||
|
* patch operation is successful.
|
||||||
|
*/
|
||||||
|
service.patchUsers = function patchUsers(dataSource, patches) {
|
||||||
|
|
||||||
|
// Make the PATCH request
|
||||||
|
return authenticationService.request({
|
||||||
|
method : 'PATCH',
|
||||||
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/users',
|
||||||
|
data : patches
|
||||||
|
})
|
||||||
|
|
||||||
|
// Clear the cache
|
||||||
|
.then(function usersPatched(patchResponse){
|
||||||
|
cacheService.users.removeAll();
|
||||||
|
return patchResponse;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return service;
|
return service;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user