mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-08 14:11:21 +00:00
GUACAMOLE-5: Merge sharing profile permission editing change.
This commit is contained in:
@@ -19,12 +19,14 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.rest.connection;
|
package org.apache.guacamole.rest.connection;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||||
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.net.auth.Connection;
|
import org.apache.guacamole.net.auth.Connection;
|
||||||
import org.apache.guacamole.protocol.GuacamoleConfiguration;
|
import org.apache.guacamole.protocol.GuacamoleConfiguration;
|
||||||
|
import org.apache.guacamole.rest.sharingprofile.APISharingProfile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple connection to expose through the REST endpoints.
|
* A simple connection to expose through the REST endpoints.
|
||||||
@@ -65,6 +67,12 @@ public class APIConnection {
|
|||||||
*/
|
*/
|
||||||
private Map<String, String> attributes;
|
private Map<String, String> attributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All associated sharing profiles. If sharing profiles are not being
|
||||||
|
* queried, this may be omitted.
|
||||||
|
*/
|
||||||
|
private Collection<APISharingProfile> sharingProfiles;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The count of currently active connections using this connection.
|
* The count of currently active connections using this connection.
|
||||||
*/
|
*/
|
||||||
@@ -227,4 +235,28 @@ public class APIConnection {
|
|||||||
this.attributes = attributes;
|
this.attributes = attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a collection of all associated sharing profiles, or null if
|
||||||
|
* sharing profiles have not been queried.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A collection of all associated sharing profiles, or null if sharing
|
||||||
|
* profiles have not been queried.
|
||||||
|
*/
|
||||||
|
public Collection<APISharingProfile> getSharingProfiles() {
|
||||||
|
return sharingProfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the collection of all associated sharing profiles to the given
|
||||||
|
* collection, which may be null if sharing profiles have not been queried.
|
||||||
|
*
|
||||||
|
* @param sharingProfiles
|
||||||
|
* The collection containing all sharing profiles associated with this
|
||||||
|
* connection, or null if sharing profiles have not been queried.
|
||||||
|
*/
|
||||||
|
public void setSharingProfiles(Collection<APISharingProfile> sharingProfiles) {
|
||||||
|
this.sharingProfiles = sharingProfiles;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -28,16 +28,20 @@ import java.util.Map;
|
|||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.net.auth.Connection;
|
import org.apache.guacamole.net.auth.Connection;
|
||||||
import org.apache.guacamole.net.auth.ConnectionGroup;
|
import org.apache.guacamole.net.auth.ConnectionGroup;
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.SharingProfile;
|
||||||
|
import org.apache.guacamole.net.auth.User;
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
import org.apache.guacamole.net.auth.permission.ObjectPermission;
|
import org.apache.guacamole.net.auth.permission.ObjectPermission;
|
||||||
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
|
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
|
||||||
import org.apache.guacamole.rest.connection.APIConnection;
|
import org.apache.guacamole.rest.connection.APIConnection;
|
||||||
|
import org.apache.guacamole.rest.sharingprofile.APISharingProfile;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to the entire tree of connection groups and their
|
* Provides access to the entire tree of connection groups, their
|
||||||
* connections.
|
* connections, and any associated sharing profiles.
|
||||||
*
|
*
|
||||||
* @author Michael Jumper
|
* @author Michael Jumper
|
||||||
*/
|
*/
|
||||||
@@ -48,16 +52,38 @@ public class ConnectionGroupTree {
|
|||||||
*/
|
*/
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ConnectionGroupTree.class);
|
private static final Logger logger = LoggerFactory.getLogger(ConnectionGroupTree.class);
|
||||||
|
|
||||||
/**
|
|
||||||
* The context of the user obtaining this tree.
|
|
||||||
*/
|
|
||||||
private final UserContext userContext;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The root connection group as an APIConnectionGroup.
|
* The root connection group as an APIConnectionGroup.
|
||||||
*/
|
*/
|
||||||
private final APIConnectionGroup rootAPIGroup;
|
private final APIConnectionGroup rootAPIGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All connection permissions granted to the user obtaining this tree.
|
||||||
|
*/
|
||||||
|
private final ObjectPermissionSet connectionPermissions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All sharing profile permissions granted to the user obtaining this tree.
|
||||||
|
*/
|
||||||
|
private final ObjectPermissionSet sharingProfilePermissions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The directory of all connections visible to the user obtaining this tree.
|
||||||
|
*/
|
||||||
|
private final Directory<Connection> connectionDirectory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The directory of all connection groups visible to the user obtaining this
|
||||||
|
* tree.
|
||||||
|
*/
|
||||||
|
private final Directory<ConnectionGroup> connectionGroupDirectory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The directory of all sharing profiles visible to the user obtaining this
|
||||||
|
* tree.
|
||||||
|
*/
|
||||||
|
private final Directory<SharingProfile> sharingProfileDirectory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All connection groups that have been retrieved, stored by their
|
* All connection groups that have been retrieved, stored by their
|
||||||
* identifiers.
|
* identifiers.
|
||||||
@@ -65,6 +91,12 @@ public class ConnectionGroupTree {
|
|||||||
private final Map<String, APIConnectionGroup> retrievedGroups =
|
private final Map<String, APIConnectionGroup> retrievedGroups =
|
||||||
new HashMap<String, APIConnectionGroup>();
|
new HashMap<String, APIConnectionGroup>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All connections that have been retrieved, stored by their identifiers.
|
||||||
|
*/
|
||||||
|
private final Map<String, APIConnection> retrievedConnections =
|
||||||
|
new HashMap<String, APIConnection>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds each of the provided connections to the current tree as children
|
* Adds each of the provided connections to the current tree as children
|
||||||
* of their respective parents. The parent connection groups must already
|
* of their respective parents. The parent connection groups must already
|
||||||
@@ -95,7 +127,9 @@ public class ConnectionGroupTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add child
|
// Add child
|
||||||
children.add(new APIConnection(connection));
|
APIConnection apiConnection = new APIConnection(connection);
|
||||||
|
retrievedConnections.put(connection.getIdentifier(), apiConnection);
|
||||||
|
children.add(apiConnection);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +184,55 @@ public class ConnectionGroupTree {
|
|||||||
} // end for each connection group
|
} // end for each connection group
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds each of the provided sharing profiles to the current tree as
|
||||||
|
* children of their respective primary connections. The primary connections
|
||||||
|
* must already be added.
|
||||||
|
*
|
||||||
|
* @param sharingProfiles
|
||||||
|
* The sharing profiles to add to the tree.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while adding the sharing profiles to the tree.
|
||||||
|
*/
|
||||||
|
private void addSharingProfiles(Collection<SharingProfile> sharingProfiles)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Add each sharing profile to the tree
|
||||||
|
for (SharingProfile sharingProfile : sharingProfiles) {
|
||||||
|
|
||||||
|
// Retrieve the sharing profile's associated connection
|
||||||
|
String primaryConnectionIdentifier = sharingProfile.getPrimaryConnectionIdentifier();
|
||||||
|
APIConnection primaryConnection = retrievedConnections.get(primaryConnectionIdentifier);
|
||||||
|
|
||||||
|
// Add the sharing profile as a child of the primary connection
|
||||||
|
if (primaryConnection != null) {
|
||||||
|
|
||||||
|
Collection<APISharingProfile> children = primaryConnection.getSharingProfiles();
|
||||||
|
|
||||||
|
// Create child collection if it does not yet exist
|
||||||
|
if (children == null) {
|
||||||
|
children = new ArrayList<APISharingProfile>();
|
||||||
|
primaryConnection.setSharingProfiles(children);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add child
|
||||||
|
children.add(new APISharingProfile(sharingProfile));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn of internal consistency issues
|
||||||
|
else
|
||||||
|
logger.debug("Sharing profile \"{}\" cannot be added to the "
|
||||||
|
+ "tree: primary connection \"{}\" does not actually "
|
||||||
|
+ "exist.", sharingProfile.getIdentifier(),
|
||||||
|
primaryConnectionIdentifier);
|
||||||
|
|
||||||
|
} // end for each sharing profile
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds all descendants of the given parent groups to their corresponding
|
* Adds all descendants of the given parent groups to their corresponding
|
||||||
* parents already stored under root.
|
* parents already stored under root.
|
||||||
@@ -167,7 +249,7 @@ public class ConnectionGroupTree {
|
|||||||
* @throws GuacamoleException
|
* @throws GuacamoleException
|
||||||
* If an error occurs while retrieving the descendants.
|
* If an error occurs while retrieving the descendants.
|
||||||
*/
|
*/
|
||||||
private void addDescendants(Collection<ConnectionGroup> parents,
|
private void addConnectionGroupDescendants(Collection<ConnectionGroup> parents,
|
||||||
List<ObjectPermission.Type> permissions)
|
List<ObjectPermission.Type> permissions)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
@@ -185,22 +267,64 @@ public class ConnectionGroupTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter identifiers based on permissions, if requested
|
// Filter identifiers based on permissions, if requested
|
||||||
if (permissions != null && !permissions.isEmpty()) {
|
if (permissions != null && !permissions.isEmpty())
|
||||||
ObjectPermissionSet permissionSet = userContext.self().getConnectionPermissions();
|
childConnectionIdentifiers = connectionPermissions.getAccessibleObjects(
|
||||||
childConnectionIdentifiers = permissionSet.getAccessibleObjects(permissions, childConnectionIdentifiers);
|
permissions, childConnectionIdentifiers);
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve child connections
|
// Retrieve child connections
|
||||||
if (!childConnectionIdentifiers.isEmpty()) {
|
if (!childConnectionIdentifiers.isEmpty()) {
|
||||||
Collection<Connection> childConnections = userContext.getConnectionDirectory().getAll(childConnectionIdentifiers);
|
Collection<Connection> childConnections = connectionDirectory.getAll(childConnectionIdentifiers);
|
||||||
addConnections(childConnections);
|
addConnections(childConnections);
|
||||||
|
addConnectionDescendants(childConnections, permissions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve child connection groups
|
// Retrieve child connection groups
|
||||||
if (!childConnectionGroupIdentifiers.isEmpty()) {
|
if (!childConnectionGroupIdentifiers.isEmpty()) {
|
||||||
Collection<ConnectionGroup> childConnectionGroups = userContext.getConnectionGroupDirectory().getAll(childConnectionGroupIdentifiers);
|
Collection<ConnectionGroup> childConnectionGroups = connectionGroupDirectory.getAll(childConnectionGroupIdentifiers);
|
||||||
addConnectionGroups(childConnectionGroups);
|
addConnectionGroups(childConnectionGroups);
|
||||||
addDescendants(childConnectionGroups, permissions);
|
addConnectionGroupDescendants(childConnectionGroups, permissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all descendant sharing profiles of the given connections to their
|
||||||
|
* corresponding primary connections already stored under root.
|
||||||
|
*
|
||||||
|
* @param connections
|
||||||
|
* The connections whose descendant sharing profiles should be added to
|
||||||
|
* the tree.
|
||||||
|
*
|
||||||
|
* @param permissions
|
||||||
|
* If specified and non-empty, limit added sharing profiles to only
|
||||||
|
* those for which the current user has any of the given
|
||||||
|
* permissions. Otherwise, all visible sharing profiles are added.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while retrieving the descendants.
|
||||||
|
*/
|
||||||
|
private void addConnectionDescendants(Collection<Connection> connections,
|
||||||
|
List<ObjectPermission.Type> permissions)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// If no connections, nothing to do
|
||||||
|
if (connections.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Build lists of sharing profile identifiers for retrieval
|
||||||
|
Collection<String> identifiers = new ArrayList<String>();
|
||||||
|
for (Connection connection : connections)
|
||||||
|
identifiers.addAll(connection.getSharingProfileIdentifiers());
|
||||||
|
|
||||||
|
// Filter identifiers based on permissions, if requested
|
||||||
|
if (permissions != null && !permissions.isEmpty())
|
||||||
|
identifiers = sharingProfilePermissions.getAccessibleObjects(
|
||||||
|
permissions, identifiers);
|
||||||
|
|
||||||
|
// Retrieve and add all associated sharing profiles
|
||||||
|
if (!identifiers.isEmpty()) {
|
||||||
|
Collection<SharingProfile> sharingProfiles = sharingProfileDirectory.getAll(identifiers);
|
||||||
|
addSharingProfiles(sharingProfiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -229,14 +353,22 @@ public class ConnectionGroupTree {
|
|||||||
public ConnectionGroupTree(UserContext userContext, ConnectionGroup root,
|
public ConnectionGroupTree(UserContext userContext, ConnectionGroup root,
|
||||||
List<ObjectPermission.Type> permissions) throws GuacamoleException {
|
List<ObjectPermission.Type> permissions) throws GuacamoleException {
|
||||||
|
|
||||||
this.userContext = userContext;
|
|
||||||
|
|
||||||
// Store root of tree
|
// Store root of tree
|
||||||
this.rootAPIGroup = new APIConnectionGroup(root);
|
this.rootAPIGroup = new APIConnectionGroup(root);
|
||||||
retrievedGroups.put(root.getIdentifier(), this.rootAPIGroup);
|
retrievedGroups.put(root.getIdentifier(), this.rootAPIGroup);
|
||||||
|
|
||||||
|
// Store user's current permissions
|
||||||
|
User self = userContext.self();
|
||||||
|
this.connectionPermissions = self.getConnectionPermissions();
|
||||||
|
this.sharingProfilePermissions = self.getSharingProfilePermissions();
|
||||||
|
|
||||||
|
// Store required directories
|
||||||
|
this.connectionDirectory = userContext.getConnectionDirectory();
|
||||||
|
this.connectionGroupDirectory = userContext.getConnectionGroupDirectory();
|
||||||
|
this.sharingProfileDirectory = userContext.getSharingProfileDirectory();
|
||||||
|
|
||||||
// Add all descendants
|
// Add all descendants
|
||||||
addDescendants(Collections.singleton(root), permissions);
|
addConnectionGroupDescendants(Collections.singleton(root), permissions);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -67,6 +67,17 @@ angular.module('groupList').directive('guacGroupList', [function guacGroupList()
|
|||||||
*/
|
*/
|
||||||
connectionGroupTemplate : '=',
|
connectionGroupTemplate : '=',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL or ID of the Angular template to use when rendering a
|
||||||
|
* sharing profile. The @link{GroupListItem} associated with that
|
||||||
|
* sharing profile will be exposed within the scope of the template
|
||||||
|
* as <code>item</code>, and the arbitrary context object, if any,
|
||||||
|
* will be exposed as <code>context</code>.
|
||||||
|
*
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
sharingProfileTemplate : '=',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the root of the connection group hierarchy given should
|
* Whether the root of the connection group hierarchy given should
|
||||||
* be shown. If false (the default), only the descendants of the
|
* be shown. If false (the default), only the descendants of the
|
||||||
@@ -165,6 +176,22 @@ angular.module('groupList').directive('guacGroupList', [function guacGroupList()
|
|||||||
return item.isConnectionGroup && !!$scope.connectionGroupTemplate;
|
return item.isConnectionGroup && !!$scope.connectionGroupTemplate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given item represents a sharing profile that
|
||||||
|
* can be displayed. If there is no sharing profile template, then
|
||||||
|
* no sharing profile is visible.
|
||||||
|
*
|
||||||
|
* @param {GroupListItem} item
|
||||||
|
* The item to check.
|
||||||
|
*
|
||||||
|
* @returns {Boolean}
|
||||||
|
* true if the given item is a sharing profile that can be
|
||||||
|
* displayed, false otherwise.
|
||||||
|
*/
|
||||||
|
$scope.isVisibleSharingProfile = function isVisibleSharingProfile(item) {
|
||||||
|
return item.isSharingProfile && !!$scope.sharingProfileTemplate;
|
||||||
|
};
|
||||||
|
|
||||||
// Set contents whenever the connection group is assigned or changed
|
// Set contents whenever the connection group is assigned or changed
|
||||||
$scope.$watch('connectionGroups', function setContents(connectionGroups) {
|
$scope.$watch('connectionGroups', function setContents(connectionGroups) {
|
||||||
|
|
||||||
@@ -185,7 +212,8 @@ angular.module('groupList').directive('guacGroupList', [function guacGroupList()
|
|||||||
|
|
||||||
// Create root item for current connection group
|
// Create root item for current connection group
|
||||||
var rootItem = GroupListItem.fromConnectionGroup(dataSource, connectionGroup,
|
var rootItem = GroupListItem.fromConnectionGroup(dataSource, connectionGroup,
|
||||||
!!$scope.connectionTemplate, countActiveConnections);
|
!!$scope.connectionTemplate, !!$scope.sharingProfileTemplate,
|
||||||
|
countActiveConnections);
|
||||||
|
|
||||||
// If root group is to be shown, add it as a root item
|
// If root group is to be shown, add it as a root item
|
||||||
if ($scope.showRootGroup)
|
if ($scope.showRootGroup)
|
||||||
|
@@ -1,38 +1,60 @@
|
|||||||
<div class="group-list">
|
<div class="group-list">
|
||||||
|
|
||||||
<script type="text/ng-template" id="nestedGroup.html">
|
<script type="text/ng-template" id="nestedItem.html">
|
||||||
|
|
||||||
<!-- Connection -->
|
<!-- Connection -->
|
||||||
<div class="connection" ng-show="isVisibleConnection(item)">
|
<div class="connection expandable" ng-if="isVisibleConnection(item)"
|
||||||
|
ng-class="{expanded: item.isExpanded, empty: !item.children.length}">
|
||||||
<div class="caption">
|
<div class="caption">
|
||||||
|
|
||||||
|
<!-- Expand/collapse icon -->
|
||||||
|
<div class="icon expand" ng-click="toggleExpanded(item)"
|
||||||
|
ng-if="sharingProfileTemplate"></div>
|
||||||
|
|
||||||
<ng-include src="connectionTemplate"/>
|
<ng-include src="connectionTemplate"/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Children of this connection -->
|
||||||
|
<div class="children" ng-show="item.isExpanded">
|
||||||
|
<div class="list-item" ng-repeat="item in item.children | orderBy : 'name'"
|
||||||
|
ng-include="'nestedItem.html'"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Connection group -->
|
<!-- Connection group -->
|
||||||
<div class="group" ng-show="isVisibleConnectionGroup(item)">
|
<div class="group expandable" ng-if="isVisibleConnectionGroup(item)"
|
||||||
|
ng-class="{expanded: item.isExpanded, empty: !item.children.length, balancer: item.isBalancing}">
|
||||||
<div class="caption">
|
<div class="caption">
|
||||||
|
|
||||||
<!-- Connection group icon -->
|
<!-- Expand/collapse icon -->
|
||||||
<div class="icon group type" ng-click="toggleExpanded(item)"
|
<div class="icon expand" ng-click="toggleExpanded(item)"></div>
|
||||||
ng-class="{expanded: item.isExpanded, empty: !item.children.length, balancer: item.isBalancing}"></div>
|
|
||||||
|
|
||||||
<ng-include src="connectionGroupTemplate"/>
|
<ng-include src="connectionGroupTemplate"/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Children of this group -->
|
<!-- Children of this group -->
|
||||||
<div class="children" ng-show="item.isExpanded">
|
<div class="children" ng-if="item.isExpanded">
|
||||||
<div class="list-item" ng-repeat="item in item.children | orderBy : 'name'" ng-include="'nestedGroup.html'">
|
<div class="list-item" ng-repeat="item in item.children | orderBy : 'name'"
|
||||||
|
ng-include="'nestedItem.html'"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Sharing profile -->
|
||||||
|
<div class="sharing-profile" ng-show="isVisibleSharingProfile(item)">
|
||||||
|
<div class="caption">
|
||||||
|
<ng-include src="sharingProfileTemplate"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Root-level connections / groups -->
|
<!-- Root-level connections / groups -->
|
||||||
<div class="group-list-page">
|
<div class="group-list-page">
|
||||||
<div class="list-item" ng-repeat="item in childrenPage" ng-include="'nestedGroup.html'"></div>
|
<div class="list-item" ng-repeat="item in childrenPage" ng-include="'nestedItem.html'"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Pager for connections / groups -->
|
<!-- Pager for connections / groups -->
|
||||||
|
@@ -37,16 +37,16 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
template = template || {};
|
template = template || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The identifier of the data source associated with the connection or
|
* The identifier of the data source associated with the connection,
|
||||||
* connection group this item represents.
|
* connection group, or sharing profile this item represents.
|
||||||
*
|
*
|
||||||
* @type String
|
* @type String
|
||||||
*/
|
*/
|
||||||
this.dataSource = template.dataSource;
|
this.dataSource = template.dataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The unique identifier associated with the connection or connection
|
* The unique identifier associated with the connection, connection
|
||||||
* group this item represents.
|
* group, or sharing profile this item represents.
|
||||||
*
|
*
|
||||||
* @type String
|
* @type String
|
||||||
*/
|
*/
|
||||||
@@ -78,7 +78,7 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this item represents a connection. If this item represents
|
* Whether this item represents a connection. If this item represents
|
||||||
* a connection group, this MUST be false.
|
* a connection group or sharing profile, this MUST be false.
|
||||||
*
|
*
|
||||||
* @type Boolean
|
* @type Boolean
|
||||||
*/
|
*/
|
||||||
@@ -86,12 +86,20 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this item represents a connection group. If this item
|
* Whether this item represents a connection group. If this item
|
||||||
* represents a connection, this MUST be false.
|
* represents a connection or sharing profile, this MUST be false.
|
||||||
*
|
*
|
||||||
* @type Boolean
|
* @type Boolean
|
||||||
*/
|
*/
|
||||||
this.isConnectionGroup = template.isConnectionGroup;
|
this.isConnectionGroup = template.isConnectionGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this item represents a sharing profile. If this item
|
||||||
|
* represents a connection or connection group, this MUST be false.
|
||||||
|
*
|
||||||
|
* @type Boolean
|
||||||
|
*/
|
||||||
|
this.isSharingProfile = template.isSharingProfile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this item represents a balancing connection group.
|
* Whether this item represents a balancing connection group.
|
||||||
*
|
*
|
||||||
@@ -107,8 +115,8 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
this.isExpanded = template.isExpanded;
|
this.isExpanded = template.isExpanded;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of currently active users for this connection or
|
* Returns the number of currently active users for this connection,
|
||||||
* connection group, if known.
|
* connection group, or sharing profile, if known.
|
||||||
*
|
*
|
||||||
* @type Number
|
* @type Number
|
||||||
*/
|
*/
|
||||||
@@ -117,10 +125,10 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The connection or connection group whose data is exposed within
|
* The connection, connection group, or sharing profile whose data is
|
||||||
* this GroupListItem.
|
* exposed within this GroupListItem.
|
||||||
*
|
*
|
||||||
* @type Connection|ConnectionGroup
|
* @type Connection|ConnectionGroup|SharingProfile
|
||||||
*/
|
*/
|
||||||
this.wrappedItem = template.wrappedItem;
|
this.wrappedItem = template.wrappedItem;
|
||||||
|
|
||||||
@@ -137,6 +145,10 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
* The connection whose contents should be represented by the new
|
* The connection whose contents should be represented by the new
|
||||||
* GroupListItem.
|
* GroupListItem.
|
||||||
*
|
*
|
||||||
|
* @param {Boolean} [includeSharingProfiles=true]
|
||||||
|
* Whether sharing profiles should be included in the contents of the
|
||||||
|
* resulting GroupListItem. By default, sharing profiles are included.
|
||||||
|
*
|
||||||
* @param {Function} [countActiveConnections]
|
* @param {Function} [countActiveConnections]
|
||||||
* A getter which returns the current number of active connections for
|
* A getter which returns the current number of active connections for
|
||||||
* the given connection. If omitted, the number of active connections
|
* the given connection. If omitted, the number of active connections
|
||||||
@@ -148,7 +160,17 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
* A new GroupListItem which represents the given connection.
|
* A new GroupListItem which represents the given connection.
|
||||||
*/
|
*/
|
||||||
GroupListItem.fromConnection = function fromConnection(dataSource,
|
GroupListItem.fromConnection = function fromConnection(dataSource,
|
||||||
connection, countActiveConnections) {
|
connection, includeSharingProfiles, countActiveConnections) {
|
||||||
|
|
||||||
|
var children = [];
|
||||||
|
|
||||||
|
// Add any sharing profiles
|
||||||
|
if (connection.sharingProfiles && includeSharingProfiles !== false) {
|
||||||
|
connection.sharingProfiles.forEach(function addSharingProfile(child) {
|
||||||
|
children.push(GroupListItem.fromSharingProfile(dataSource,
|
||||||
|
child, countActiveConnections));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Return item representing the given connection
|
// Return item representing the given connection
|
||||||
return new GroupListItem({
|
return new GroupListItem({
|
||||||
@@ -162,7 +184,11 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
// Type information
|
// Type information
|
||||||
isConnection : true,
|
isConnection : true,
|
||||||
isConnectionGroup : false,
|
isConnectionGroup : false,
|
||||||
|
isSharingProfile : false,
|
||||||
|
|
||||||
|
// Already-converted children
|
||||||
|
children : children,
|
||||||
|
|
||||||
// Count of currently active connections using this connection
|
// Count of currently active connections using this connection
|
||||||
getActiveConnections : function getActiveConnections() {
|
getActiveConnections : function getActiveConnections() {
|
||||||
|
|
||||||
@@ -197,6 +223,10 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
* Whether connections should be included in the contents of the
|
* Whether connections should be included in the contents of the
|
||||||
* resulting GroupListItem. By default, connections are included.
|
* resulting GroupListItem. By default, connections are included.
|
||||||
*
|
*
|
||||||
|
* @param {Boolean} [includeSharingProfiles=true]
|
||||||
|
* Whether sharing profiles should be included in the contents of the
|
||||||
|
* resulting GroupListItem. By default, sharing profiles are included.
|
||||||
|
*
|
||||||
* @param {Function} [countActiveConnections]
|
* @param {Function} [countActiveConnections]
|
||||||
* A getter which returns the current number of active connections for
|
* A getter which returns the current number of active connections for
|
||||||
* the given connection. If omitted, the number of active connections
|
* the given connection. If omitted, the number of active connections
|
||||||
@@ -216,8 +246,8 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
* including all descendants.
|
* including all descendants.
|
||||||
*/
|
*/
|
||||||
GroupListItem.fromConnectionGroup = function fromConnectionGroup(dataSource,
|
GroupListItem.fromConnectionGroup = function fromConnectionGroup(dataSource,
|
||||||
connectionGroup, includeConnections, countActiveConnections,
|
connectionGroup, includeConnections, includeSharingProfiles,
|
||||||
countActiveConnectionGroups) {
|
countActiveConnections, countActiveConnectionGroups) {
|
||||||
|
|
||||||
var children = [];
|
var children = [];
|
||||||
|
|
||||||
@@ -225,7 +255,7 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
if (connectionGroup.childConnections && includeConnections !== false) {
|
if (connectionGroup.childConnections && includeConnections !== false) {
|
||||||
connectionGroup.childConnections.forEach(function addChildConnection(child) {
|
connectionGroup.childConnections.forEach(function addChildConnection(child) {
|
||||||
children.push(GroupListItem.fromConnection(dataSource, child,
|
children.push(GroupListItem.fromConnection(dataSource, child,
|
||||||
countActiveConnections));
|
includeSharingProfiles, countActiveConnections));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,8 +263,8 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
if (connectionGroup.childConnectionGroups) {
|
if (connectionGroup.childConnectionGroups) {
|
||||||
connectionGroup.childConnectionGroups.forEach(function addChildGroup(child) {
|
connectionGroup.childConnectionGroups.forEach(function addChildGroup(child) {
|
||||||
children.push(GroupListItem.fromConnectionGroup(dataSource,
|
children.push(GroupListItem.fromConnectionGroup(dataSource,
|
||||||
child, includeConnections, countActiveConnections,
|
child, includeConnections, includeSharingProfiles,
|
||||||
countActiveConnectionGroups));
|
countActiveConnections, countActiveConnectionGroups));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,6 +279,7 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
// Type information
|
// Type information
|
||||||
isConnection : false,
|
isConnection : false,
|
||||||
isConnectionGroup : true,
|
isConnectionGroup : true,
|
||||||
|
isSharingProfile : false,
|
||||||
isBalancing : connectionGroup.type === ConnectionGroup.Type.BALANCING,
|
isBalancing : connectionGroup.type === ConnectionGroup.Type.BALANCING,
|
||||||
|
|
||||||
// Already-converted children
|
// Already-converted children
|
||||||
@@ -273,6 +304,44 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new GroupListItem using the contents of the given sharing
|
||||||
|
* profile.
|
||||||
|
*
|
||||||
|
* @param {String} dataSource
|
||||||
|
* The identifier of the data source containing the given sharing
|
||||||
|
* profile.
|
||||||
|
*
|
||||||
|
* @param {SharingProfile} sharingProfile
|
||||||
|
* The sharing profile whose contents should be represented by the new
|
||||||
|
* GroupListItem.
|
||||||
|
*
|
||||||
|
* @returns {GroupListItem}
|
||||||
|
* A new GroupListItem which represents the given sharing profile.
|
||||||
|
*/
|
||||||
|
GroupListItem.fromSharingProfile = function fromSharingProfile(dataSource,
|
||||||
|
sharingProfile) {
|
||||||
|
|
||||||
|
// Return item representing the given sharing profile
|
||||||
|
return new GroupListItem({
|
||||||
|
|
||||||
|
// Identifying information
|
||||||
|
name : sharingProfile.name,
|
||||||
|
identifier : sharingProfile.identifier,
|
||||||
|
dataSource : dataSource,
|
||||||
|
|
||||||
|
// Type information
|
||||||
|
isConnection : false,
|
||||||
|
isConnectionGroup : false,
|
||||||
|
isSharingProfile : true,
|
||||||
|
|
||||||
|
// Wrapped item
|
||||||
|
wrappedItem : sharingProfile
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
return GroupListItem;
|
return GroupListItem;
|
||||||
|
|
||||||
}]);
|
}]);
|
||||||
|
@@ -1,19 +1,15 @@
|
|||||||
<a ng-href="#/client/{{context.getClientIdentifier(item)}}">
|
<a ng-href="#/client/{{context.getClientIdentifier(item)}}"
|
||||||
|
ng-class="{active: item.getActiveConnections()}">
|
||||||
|
|
||||||
<div class="caption" ng-class="{active: item.getActiveConnections()}">
|
<!-- Connection icon -->
|
||||||
|
<div class="icon type" ng-class="item.protocol"></div>
|
||||||
|
|
||||||
<!-- Connection icon -->
|
<!-- Connection name -->
|
||||||
<div class="protocol">
|
<span class="name">{{item.name}}</span>
|
||||||
<div class="icon type" ng-class="item.protocol"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Connection name -->
|
<!-- Active user count -->
|
||||||
<span class="name">{{item.name}}</span>
|
<span class="activeUserCount" ng-show="item.getActiveConnections()"
|
||||||
|
translate="HOME.INFO_ACTIVE_USER_COUNT"
|
||||||
<!-- Active user count -->
|
translate-values="{USERS: item.getActiveConnections()}"></span>
|
||||||
<span class="activeUserCount" ng-show="item.getActiveConnections()"
|
|
||||||
translate="HOME.INFO_ACTIVE_USER_COUNT"
|
|
||||||
translate-values="{USERS: item.getActiveConnections()}"></span>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</a>
|
</a>
|
||||||
|
@@ -44,15 +44,16 @@
|
|||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection:hover {
|
.recent-connections .connection:hover {
|
||||||
background: #CDA;
|
background: #CDA;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection .thumbnail {
|
.recent-connections .connection .thumbnail {
|
||||||
|
display: block;
|
||||||
margin: 0.5em;
|
margin: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection .thumbnail > * {
|
.recent-connections .connection .thumbnail > * {
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
background: black;
|
background: black;
|
||||||
box-shadow: 1px 1px 5px black;
|
box-shadow: 1px 1px 5px black;
|
||||||
@@ -60,14 +61,6 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.recent-connections .connection .thumbnail {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.recent-connections .protocol {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.caption * {
|
.caption * {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
@@ -164,14 +164,12 @@ div.section {
|
|||||||
background-image: url('images/action-icons/guac-monitor-add.png');
|
background-image: url('images/action-icons/guac-monitor-add.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.protocol {
|
.connection .icon,
|
||||||
|
.connection-group .icon,
|
||||||
|
.sharing-profile .icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
|
||||||
|
|
||||||
.protocol .icon {
|
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
background-image: url('images/protocol-icons/guac-plug.png');
|
|
||||||
background-size: 16px 16px;
|
background-size: 16px 16px;
|
||||||
-moz-background-size: 16px 16px;
|
-moz-background-size: 16px 16px;
|
||||||
-webkit-background-size: 16px 16px;
|
-webkit-background-size: 16px 16px;
|
||||||
@@ -180,44 +178,86 @@ div.section {
|
|||||||
background-position: center center;
|
background-position: center center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.protocol .icon.ssh,
|
.group > .caption .icon {
|
||||||
.protocol .icon.telnet {
|
background-image: url('images/folder-closed.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
.group.expanded > .caption .icon {
|
||||||
|
background-image: url('images/folder-open.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
.connection .icon {
|
||||||
|
background-image: url('images/protocol-icons/guac-plug.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
.connection .icon.ssh,
|
||||||
|
.connection .icon.telnet {
|
||||||
background-image: url('images/protocol-icons/guac-text.png');
|
background-image: url('images/protocol-icons/guac-text.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.protocol .icon.vnc,
|
.connection .icon.vnc,
|
||||||
.protocol .icon.rdp {
|
.connection .icon.rdp {
|
||||||
background-image: url('images/protocol-icons/guac-monitor.png');
|
background-image: url('images/protocol-icons/guac-monitor.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sharing-profile .icon {
|
||||||
|
background-image: url('images/share.png');
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Groups
|
* Groups
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.group > .children {
|
.expandable > .children {
|
||||||
margin-left: 13px;
|
margin-left: 13px;
|
||||||
padding-left: 6px;
|
padding-left: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group .icon.group.type.empty.balancer {
|
.group.empty.balancer .icon {
|
||||||
opacity: 1;
|
|
||||||
background-image: url('images/protocol-icons/guac-monitor.png');
|
background-image: url('images/protocol-icons/guac-monitor.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.group.expanded > .children {
|
.expandable.expanded > .children > .list-item {
|
||||||
display: block;
|
position: relative;
|
||||||
border-left: 1px dotted rgba(0, 0, 0, 0.25);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.group > .caption .icon.group {
|
.expandable.expanded > .children > .list-item:before,
|
||||||
opacity: 0.75;
|
.expandable.expanded > .children > .list-item:after {
|
||||||
|
display: block;
|
||||||
|
content: ' ';
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expandable.expanded > .children > .list-item:before {
|
||||||
|
border-left: 1px solid #BBB;
|
||||||
|
left: -13px;
|
||||||
|
top: -0.75em;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expandable.expanded > .children > .list-item:last-child:before {
|
||||||
|
height: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expandable.expanded > .children > .list-item:after {
|
||||||
|
display: block;
|
||||||
|
content: ' ';
|
||||||
|
border-bottom: 1px solid #BBB;
|
||||||
|
left: -13px;
|
||||||
|
width: 13px;
|
||||||
|
top: 0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expandable > .caption .icon.expand {
|
||||||
background-image: url('images/group-icons/guac-closed.png');
|
background-image: url('images/group-icons/guac-closed.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.group .icon.type.group.expanded {
|
.expandable.expanded > .caption .icon.expand {
|
||||||
background-image: url('images/group-icons/guac-open.png');
|
background-image: url('images/group-icons/guac-open.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.group .icon.type.group.empty {
|
.expandable.empty > .caption .icon.expand {
|
||||||
opacity: 0.25;
|
opacity: 0.25;
|
||||||
background-image: url('images/group-icons/guac-open.png');
|
background-image: url('images/group-icons/guac-open.png');
|
||||||
}
|
}
|
||||||
|
@@ -633,6 +633,10 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
|
|||||||
{
|
{
|
||||||
label: "MANAGE_USER.FIELD_HEADER_CREATE_NEW_CONNECTION_GROUPS",
|
label: "MANAGE_USER.FIELD_HEADER_CREATE_NEW_CONNECTION_GROUPS",
|
||||||
value: PermissionSet.SystemPermissionType.CREATE_CONNECTION_GROUP
|
value: PermissionSet.SystemPermissionType.CREATE_CONNECTION_GROUP
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "MANAGE_USER.FIELD_HEADER_CREATE_NEW_SHARING_PROFILES",
|
||||||
|
value: PermissionSet.SystemPermissionType.CREATE_SHARING_PROFILE
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -705,10 +709,10 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
|
|||||||
$scope.systemPermissionChanged = function systemPermissionChanged(type) {
|
$scope.systemPermissionChanged = function systemPermissionChanged(type) {
|
||||||
|
|
||||||
// Determine current permission setting
|
// Determine current permission setting
|
||||||
var value = $scope.permissionFlags.systemPermissions[type];
|
var granted = $scope.permissionFlags.systemPermissions[type];
|
||||||
|
|
||||||
// Add/remove permission depending on flag state
|
// Add/remove permission depending on flag state
|
||||||
if (value)
|
if (granted)
|
||||||
addSystemPermission(type);
|
addSystemPermission(type);
|
||||||
else
|
else
|
||||||
removeSystemPermission(type);
|
removeSystemPermission(type);
|
||||||
@@ -775,10 +779,10 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
|
|||||||
$scope.userPermissionChanged = function userPermissionChanged(type, identifier) {
|
$scope.userPermissionChanged = function userPermissionChanged(type, identifier) {
|
||||||
|
|
||||||
// Determine current permission setting
|
// Determine current permission setting
|
||||||
var value = $scope.permissionFlags.userPermissions[type][identifier];
|
var granted = $scope.permissionFlags.userPermissions[type][identifier];
|
||||||
|
|
||||||
// Add/remove permission depending on flag state
|
// Add/remove permission depending on flag state
|
||||||
if (value)
|
if (granted)
|
||||||
addUserPermission(type, identifier);
|
addUserPermission(type, identifier);
|
||||||
else
|
else
|
||||||
removeUserPermission(type, identifier);
|
removeUserPermission(type, identifier);
|
||||||
@@ -861,6 +865,45 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the permissionsAdded and permissionsRemoved permission sets to
|
||||||
|
* reflect the addition of the given sharing profile permission.
|
||||||
|
*
|
||||||
|
* @param {String} identifier
|
||||||
|
* The identifier of the sharing profile to add READ permission for.
|
||||||
|
*/
|
||||||
|
var addSharingProfilePermission = function addSharingProfilePermission(identifier) {
|
||||||
|
|
||||||
|
// If permission was previously removed, simply un-remove it
|
||||||
|
if (PermissionSet.hasSharingProfilePermission(permissionsRemoved, PermissionSet.ObjectPermissionType.READ, identifier))
|
||||||
|
PermissionSet.removeSharingProfilePermission(permissionsRemoved, PermissionSet.ObjectPermissionType.READ, identifier);
|
||||||
|
|
||||||
|
// Otherwise, explicitly add the permission
|
||||||
|
else
|
||||||
|
PermissionSet.addSharingProfilePermission(permissionsAdded, PermissionSet.ObjectPermissionType.READ, identifier);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the permissionsAdded and permissionsRemoved permission sets to
|
||||||
|
* reflect the removal of the given sharing profile permission.
|
||||||
|
*
|
||||||
|
* @param {String} identifier
|
||||||
|
* The identifier of the sharing profile to remove READ permission for.
|
||||||
|
*/
|
||||||
|
var removeSharingProfilePermission = function removeSharingProfilePermission(identifier) {
|
||||||
|
|
||||||
|
// If permission was previously added, simply un-add it
|
||||||
|
if (PermissionSet.hasSharingProfilePermission(permissionsAdded, PermissionSet.ObjectPermissionType.READ, identifier))
|
||||||
|
PermissionSet.removeSharingProfilePermission(permissionsAdded, PermissionSet.ObjectPermissionType.READ, identifier);
|
||||||
|
|
||||||
|
// Otherwise, explicitly remove the permission
|
||||||
|
else
|
||||||
|
PermissionSet.addSharingProfilePermission(permissionsRemoved, PermissionSet.ObjectPermissionType.READ, identifier);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Expose permission query and modification functions to group list template
|
// Expose permission query and modification functions to group list template
|
||||||
$scope.groupListContext = {
|
$scope.groupListContext = {
|
||||||
|
|
||||||
@@ -888,10 +931,10 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
|
|||||||
connectionPermissionChanged : function connectionPermissionChanged(identifier) {
|
connectionPermissionChanged : function connectionPermissionChanged(identifier) {
|
||||||
|
|
||||||
// Determine current permission setting
|
// Determine current permission setting
|
||||||
var value = $scope.permissionFlags.connectionPermissions.READ[identifier];
|
var granted = $scope.permissionFlags.connectionPermissions.READ[identifier];
|
||||||
|
|
||||||
// Add/remove permission depending on flag state
|
// Add/remove permission depending on flag state
|
||||||
if (value)
|
if (granted)
|
||||||
addConnectionPermission(identifier);
|
addConnectionPermission(identifier);
|
||||||
else
|
else
|
||||||
removeConnectionPermission(identifier);
|
removeConnectionPermission(identifier);
|
||||||
@@ -910,14 +953,36 @@ angular.module('manage').controller('manageUserController', ['$scope', '$injecto
|
|||||||
connectionGroupPermissionChanged : function connectionGroupPermissionChanged(identifier) {
|
connectionGroupPermissionChanged : function connectionGroupPermissionChanged(identifier) {
|
||||||
|
|
||||||
// Determine current permission setting
|
// Determine current permission setting
|
||||||
var value = $scope.permissionFlags.connectionGroupPermissions.READ[identifier];
|
var granted = $scope.permissionFlags.connectionGroupPermissions.READ[identifier];
|
||||||
|
|
||||||
// Add/remove permission depending on flag state
|
// Add/remove permission depending on flag state
|
||||||
if (value)
|
if (granted)
|
||||||
addConnectionGroupPermission(identifier);
|
addConnectionGroupPermission(identifier);
|
||||||
else
|
else
|
||||||
removeConnectionGroupPermission(identifier);
|
removeConnectionGroupPermission(identifier);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the controller that a change has been made to the given
|
||||||
|
* sharing profile permission for the user being edited. This only
|
||||||
|
* applies to READ permissions.
|
||||||
|
*
|
||||||
|
* @param {String} identifier
|
||||||
|
* The identifier of the sharing profile affected by the changed
|
||||||
|
* permission.
|
||||||
|
*/
|
||||||
|
sharingProfilePermissionChanged : function sharingProfilePermissionChanged(identifier) {
|
||||||
|
|
||||||
|
// Determine current permission setting
|
||||||
|
var granted = $scope.permissionFlags.sharingProfilePermissions.READ[identifier];
|
||||||
|
|
||||||
|
// Add/remove permission depending on flag state
|
||||||
|
if (granted)
|
||||||
|
addSharingProfilePermission(identifier);
|
||||||
|
else
|
||||||
|
removeSharingProfilePermission(identifier);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@@ -1,7 +1,13 @@
|
|||||||
<div class="choice">
|
<div class="choice">
|
||||||
|
|
||||||
|
<!-- Connection group icon -->
|
||||||
|
<div class="icon type"></div>
|
||||||
|
|
||||||
|
<!-- Permission checkbox -->
|
||||||
<input type="checkbox" ng-model="context.getPermissionFlags().connectionGroupPermissions.READ[item.identifier]"
|
<input type="checkbox" ng-model="context.getPermissionFlags().connectionGroupPermissions.READ[item.identifier]"
|
||||||
ng-change="context.connectionGroupPermissionChanged(item.identifier)"/>
|
ng-change="context.connectionGroupPermissionChanged(item.identifier)"/>
|
||||||
|
|
||||||
|
<!-- Connection group name -->
|
||||||
<span class="name">{{item.name}}</span>
|
<span class="name">{{item.name}}</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,11 +1,9 @@
|
|||||||
<div class="choice">
|
<div class="choice">
|
||||||
|
|
||||||
<!-- Connection icon -->
|
<!-- Connection icon -->
|
||||||
<div class="protocol">
|
<div class="icon type" ng-class="item.protocol"></div>
|
||||||
<div class="icon type" ng-class="item.protocol"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Checkbox -->
|
<!-- Permission checkbox -->
|
||||||
<input type="checkbox" ng-model="context.getPermissionFlags().connectionPermissions.READ[item.identifier]"
|
<input type="checkbox" ng-model="context.getPermissionFlags().connectionPermissions.READ[item.identifier]"
|
||||||
ng-change="context.connectionPermissionChanged(item.identifier)"/>
|
ng-change="context.connectionPermissionChanged(item.identifier)"/>
|
||||||
|
|
||||||
|
@@ -79,6 +79,7 @@
|
|||||||
context="groupListContext"
|
context="groupListContext"
|
||||||
connection-groups="filteredRootGroups"
|
connection-groups="filteredRootGroups"
|
||||||
connection-template="'app/manage/templates/connectionPermission.html'"
|
connection-template="'app/manage/templates/connectionPermission.html'"
|
||||||
|
sharing-profile-template="'app/manage/templates/sharingProfilePermission.html'"
|
||||||
connection-group-template="'app/manage/templates/connectionGroupPermission.html'"
|
connection-group-template="'app/manage/templates/connectionGroupPermission.html'"
|
||||||
page-size="20"/>
|
page-size="20"/>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -0,0 +1,13 @@
|
|||||||
|
<div class="choice">
|
||||||
|
|
||||||
|
<!-- Sharing profile icon -->
|
||||||
|
<div class="icon type"></div>
|
||||||
|
|
||||||
|
<!-- Permission checkbox -->
|
||||||
|
<input type="checkbox" ng-model="context.getPermissionFlags().sharingProfilePermissions.READ[item.identifier]"
|
||||||
|
ng-change="context.sharingProfilePermissionChanged(item.identifier)"/>
|
||||||
|
|
||||||
|
<!-- Sharing profile name -->
|
||||||
|
<span class="name">{{item.name}}</span>
|
||||||
|
|
||||||
|
</div>
|
@@ -175,6 +175,10 @@ angular.module('rest').factory('permissionService', ['$injector',
|
|||||||
addObjectPatchOperations(patch, operation, "/connectionGroupPermissions",
|
addObjectPatchOperations(patch, operation, "/connectionGroupPermissions",
|
||||||
permissions.connectionGroupPermissions);
|
permissions.connectionGroupPermissions);
|
||||||
|
|
||||||
|
// Add sharing profile permission operations to patch
|
||||||
|
addObjectPatchOperations(patch, operation, "/sharingProfilePermissions",
|
||||||
|
permissions.sharingProfilePermissions);
|
||||||
|
|
||||||
// Add active connection permission operations to patch
|
// Add active connection permission operations to patch
|
||||||
addObjectPatchOperations(patch, operation, "/activeConnectionPermissions",
|
addObjectPatchOperations(patch, operation, "/activeConnectionPermissions",
|
||||||
permissions.activeConnectionPermissions);
|
permissions.activeConnectionPermissions);
|
||||||
|
@@ -95,6 +95,15 @@ angular.module('rest').factory('Connection', [function defineConnection() {
|
|||||||
*/
|
*/
|
||||||
this.activeConnections = template.activeConnections;
|
this.activeConnections = template.activeConnections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of all associated sharing profiles, if known. This property
|
||||||
|
* may be null or undefined if sharing profiles have not been queried,
|
||||||
|
* and thus the sharing profiles are unknown.
|
||||||
|
*
|
||||||
|
* @type SharingProfile[]
|
||||||
|
*/
|
||||||
|
this.sharingProfiles = template.sharingProfiles;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return Connection;
|
return Connection;
|
||||||
|
@@ -87,6 +87,25 @@ angular.module('rest').factory('PermissionFlagSet', ['PermissionSet',
|
|||||||
'ADMINISTER' : {}
|
'ADMINISTER' : {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The granted state of each permission for each sharing profile, as a
|
||||||
|
* map of object permission type string to permission map. The
|
||||||
|
* permission map is, in turn, a map of sharing profile identifier to
|
||||||
|
* boolean value. A particular permission is granted if its
|
||||||
|
* corresponding boolean value is set to true. Valid permission type
|
||||||
|
* strings are defined within PermissionSet.ObjectPermissionType.
|
||||||
|
* Permissions which are not granted may be set to false, but this is
|
||||||
|
* not required.
|
||||||
|
*
|
||||||
|
* @type Object.<String, Object.<String, Boolean>>
|
||||||
|
*/
|
||||||
|
this.sharingProfilePermissions = template.sharingProfilePermissions || {
|
||||||
|
'READ' : {},
|
||||||
|
'UPDATE' : {},
|
||||||
|
'DELETE' : {},
|
||||||
|
'ADMINISTER' : {}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The granted state of each permission for each active connection, as
|
* The granted state of each permission for each active connection, as
|
||||||
* a map of object permission type string to permission map. The
|
* a map of object permission type string to permission map. The
|
||||||
@@ -188,6 +207,9 @@ angular.module('rest').factory('PermissionFlagSet', ['PermissionSet',
|
|||||||
// Add all granted connection group permissions
|
// Add all granted connection group permissions
|
||||||
addObjectPermissions(permissionSet.connectionGroupPermissions, permissionFlagSet.connectionGroupPermissions);
|
addObjectPermissions(permissionSet.connectionGroupPermissions, permissionFlagSet.connectionGroupPermissions);
|
||||||
|
|
||||||
|
// Add all granted sharing profile permissions
|
||||||
|
addObjectPermissions(permissionSet.sharingProfilePermissions, permissionFlagSet.sharingProfilePermissions);
|
||||||
|
|
||||||
// Add all granted active connection permissions
|
// Add all granted active connection permissions
|
||||||
addObjectPermissions(permissionSet.activeConnectionPermissions, permissionFlagSet.activeConnectionPermissions);
|
addObjectPermissions(permissionSet.activeConnectionPermissions, permissionFlagSet.activeConnectionPermissions);
|
||||||
|
|
||||||
|
@@ -53,6 +53,15 @@ angular.module('rest').factory('PermissionSet', [function definePermissionSet()
|
|||||||
* @type Object.<String, String[]>
|
* @type Object.<String, String[]>
|
||||||
*/
|
*/
|
||||||
this.connectionGroupPermissions = template.connectionGroupPermissions || {};
|
this.connectionGroupPermissions = template.connectionGroupPermissions || {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of sharing profile identifiers to the corresponding array of
|
||||||
|
* granted permissions. Each permission is represented by a string
|
||||||
|
* listed within PermissionSet.ObjectPermissionType.
|
||||||
|
*
|
||||||
|
* @type Object.<String, String[]>
|
||||||
|
*/
|
||||||
|
this.sharingProfilePermissions = template.sharingProfilePermissions || {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of active connection identifiers to the corresponding array of
|
* Map of active connection identifiers to the corresponding array of
|
||||||
@@ -132,7 +141,12 @@ angular.module('rest').factory('PermissionSet', [function definePermissionSet()
|
|||||||
/**
|
/**
|
||||||
* Permission to create new connection groups.
|
* Permission to create new connection groups.
|
||||||
*/
|
*/
|
||||||
CREATE_CONNECTION_GROUP : "CREATE_CONNECTION_GROUP"
|
CREATE_CONNECTION_GROUP : "CREATE_CONNECTION_GROUP",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permission to create new sharing profiles.
|
||||||
|
*/
|
||||||
|
CREATE_SHARING_PROFILE : "CREATE_SHARING_PROFILE"
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -247,6 +261,28 @@ angular.module('rest').factory('PermissionSet', [function definePermissionSet()
|
|||||||
return hasPermission(permSet.connectionGroupPermissions, type, identifier);
|
return hasPermission(permSet.connectionGroupPermissions, type, identifier);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given permission is granted for the sharing profile
|
||||||
|
* having the given ID.
|
||||||
|
*
|
||||||
|
* @param {PermissionSet|Object} permSet
|
||||||
|
* The permission set to check.
|
||||||
|
*
|
||||||
|
* @param {String} type
|
||||||
|
* The permission to search for, as defined by
|
||||||
|
* PermissionSet.ObjectPermissionType.
|
||||||
|
*
|
||||||
|
* @param {String} identifier
|
||||||
|
* The identifier of the sharing profile to which the permission
|
||||||
|
* applies.
|
||||||
|
*
|
||||||
|
* @returns {Boolean}
|
||||||
|
* true if the permission is present (granted), false otherwise.
|
||||||
|
*/
|
||||||
|
PermissionSet.hasSharingProfilePermission = function hasSharingProfilePermission(permSet, type, identifier) {
|
||||||
|
return hasPermission(permSet.sharingProfilePermissions, type, identifier);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given permission is granted for the active
|
* Returns whether the given permission is granted for the active
|
||||||
* connection having the given ID.
|
* connection having the given ID.
|
||||||
@@ -548,6 +584,56 @@ angular.module('rest').factory('PermissionSet', [function definePermissionSet()
|
|||||||
return removeObjectPermission(permSet.connectionGroupPermissions, type, identifier);
|
return removeObjectPermission(permSet.connectionGroupPermissions, type, identifier);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given sharing profile permission applying to the sharing profile
|
||||||
|
* with the given ID to the given permission set, if not already present. If
|
||||||
|
* the permission is already present, this function has no effect.
|
||||||
|
*
|
||||||
|
* @param {PermissionSet} permSet
|
||||||
|
* The permission set to modify.
|
||||||
|
*
|
||||||
|
* @param {String} type
|
||||||
|
* The permission to add, as defined by
|
||||||
|
* PermissionSet.ObjectPermissionType.
|
||||||
|
*
|
||||||
|
* @param {String} identifier
|
||||||
|
* The identifier of the sharing profile to which the permission
|
||||||
|
* applies.
|
||||||
|
*
|
||||||
|
* @returns {Boolean}
|
||||||
|
* true if the permission was added, false if the permission was
|
||||||
|
* already present in the given permission set.
|
||||||
|
*/
|
||||||
|
PermissionSet.addSharingProfilePermission = function addSharingProfilePermission(permSet, type, identifier) {
|
||||||
|
permSet.sharingProfilePermissions = permSet.sharingProfilePermissions || {};
|
||||||
|
return addObjectPermission(permSet.sharingProfilePermissions, type, identifier);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the given sharing profile permission applying to the sharing
|
||||||
|
* profile with the given ID from the given permission set, if present. If
|
||||||
|
* the permission is not present, this function has no effect.
|
||||||
|
*
|
||||||
|
* @param {PermissionSet} permSet
|
||||||
|
* The permission set to modify.
|
||||||
|
*
|
||||||
|
* @param {String} type
|
||||||
|
* The permission to remove, as defined by
|
||||||
|
* PermissionSet.ObjectPermissionType.
|
||||||
|
*
|
||||||
|
* @param {String} identifier
|
||||||
|
* The identifier of the sharing profile to which the permission
|
||||||
|
* applies.
|
||||||
|
*
|
||||||
|
* @returns {Boolean}
|
||||||
|
* true if the permission was removed, false if the permission was not
|
||||||
|
* present in the given permission set.
|
||||||
|
*/
|
||||||
|
PermissionSet.removeSharingProfilePermission = function removeSharingProfilePermission(permSet, type, identifier) {
|
||||||
|
permSet.sharingProfilePermissions = permSet.sharingProfilePermissions || {};
|
||||||
|
return removeObjectPermission(permSet.sharingProfilePermissions, type, identifier);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the given active connection permission applying to the connection
|
* Adds the given active connection permission applying to the connection
|
||||||
* group with the given ID to the given permission set, if not already
|
* group with the given ID to the given permission set, if not already
|
||||||
|
@@ -1,19 +1,15 @@
|
|||||||
<a ng-href="#/manage/{{item.dataSource}}/connections/{{item.identifier}}">
|
<a ng-href="#/manage/{{item.dataSource}}/connections/{{item.identifier}}"
|
||||||
|
ng-class="{active: item.getActiveConnections()}">
|
||||||
|
|
||||||
<div class="caption" ng-class="{active: item.getActiveConnections()}">
|
<!-- Connection icon -->
|
||||||
|
<div class="icon type" ng-class="item.protocol"></div>
|
||||||
|
|
||||||
<!-- Connection icon -->
|
<!-- Connection name -->
|
||||||
<div class="protocol">
|
<span class="name">{{item.name}}</span>
|
||||||
<div class="icon type" ng-class="item.protocol"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Connection name -->
|
<!-- Active user count -->
|
||||||
<span class="name">{{item.name}}</span>
|
<span class="activeUserCount" ng-show="item.getActiveConnections()"
|
||||||
|
translate="SETTINGS_CONNECTIONS.INFO_ACTIVE_USER_COUNT"
|
||||||
|
translate-values="{USERS: item.getActiveConnections()}"></span>
|
||||||
|
|
||||||
<!-- Active user count -->
|
|
||||||
<span class="activeUserCount" ng-show="item.getActiveConnections()"
|
|
||||||
translate="SETTINGS_CONNECTIONS.INFO_ACTIVE_USER_COUNT"
|
|
||||||
translate-values="{USERS: item.getActiveConnections()}"></span>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</a>
|
</a>
|
||||||
|
@@ -256,6 +256,7 @@
|
|||||||
"FIELD_HEADER_CREATE_NEW_USERS" : "Create new users:",
|
"FIELD_HEADER_CREATE_NEW_USERS" : "Create new users:",
|
||||||
"FIELD_HEADER_CREATE_NEW_CONNECTIONS" : "Create new connections:",
|
"FIELD_HEADER_CREATE_NEW_CONNECTIONS" : "Create new connections:",
|
||||||
"FIELD_HEADER_CREATE_NEW_CONNECTION_GROUPS" : "Create new connection groups:",
|
"FIELD_HEADER_CREATE_NEW_CONNECTION_GROUPS" : "Create new connection groups:",
|
||||||
|
"FIELD_HEADER_CREATE_NEW_SHARING_PROFILES" : "Create new sharing profiles:",
|
||||||
"FIELD_HEADER_PASSWORD" : "@:APP.FIELD_HEADER_PASSWORD",
|
"FIELD_HEADER_PASSWORD" : "@:APP.FIELD_HEADER_PASSWORD",
|
||||||
"FIELD_HEADER_PASSWORD_AGAIN" : "@:APP.FIELD_HEADER_PASSWORD_AGAIN",
|
"FIELD_HEADER_PASSWORD_AGAIN" : "@:APP.FIELD_HEADER_PASSWORD_AGAIN",
|
||||||
"FIELD_HEADER_USERNAME" : "Username:",
|
"FIELD_HEADER_USERNAME" : "Username:",
|
||||||
|
Reference in New Issue
Block a user