mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-07 05:31:22 +00:00
Merge pull request #143 from glyptodon/readable-active-connections
GUAC-1126: Calculate active connections using the active connection service
This commit is contained in:
@@ -88,20 +88,22 @@ public class ActiveConnectionPermissionService
|
|||||||
if (canReadPermissions(user, targetUser)) {
|
if (canReadPermissions(user, targetUser)) {
|
||||||
|
|
||||||
// Only administrators may access active connections
|
// Only administrators may access active connections
|
||||||
if (!targetUser.isAdministrator())
|
boolean isAdmin = targetUser.isAdministrator();
|
||||||
return Collections.EMPTY_SET;
|
|
||||||
|
|
||||||
// Get all active connections
|
// Get all active connections
|
||||||
Collection<ActiveConnectionRecord> records = tunnelService.getActiveConnections(user);
|
Collection<ActiveConnectionRecord> records = tunnelService.getActiveConnections(user);
|
||||||
|
|
||||||
// We have READ and DELETE on all active connections
|
// We have READ, and possibly DELETE, on all active connections
|
||||||
Set<ObjectPermission> permissions = new HashSet<ObjectPermission>();
|
Set<ObjectPermission> permissions = new HashSet<ObjectPermission>();
|
||||||
for (ActiveConnectionRecord record : records) {
|
for (ActiveConnectionRecord record : records) {
|
||||||
|
|
||||||
// Add implicit READ and DELETE
|
// Add implicit READ
|
||||||
String identifier = record.getUUID().toString();
|
String identifier = record.getUUID().toString();
|
||||||
permissions.add(new ObjectPermission(ObjectPermission.Type.READ, identifier));
|
permissions.add(new ObjectPermission(ObjectPermission.Type.READ, identifier));
|
||||||
permissions.add(new ObjectPermission(ObjectPermission.Type.DELETE, identifier));
|
|
||||||
|
// If we're and admin, then we also have DELETE
|
||||||
|
if (isAdmin)
|
||||||
|
permissions.add(new ObjectPermission(ObjectPermission.Type.DELETE, identifier));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,6 +26,7 @@ import com.google.inject.Inject;
|
|||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||||
@@ -62,35 +63,43 @@ public class ActiveConnectionService
|
|||||||
public TrackedActiveConnection retrieveObject(AuthenticatedUser user,
|
public TrackedActiveConnection retrieveObject(AuthenticatedUser user,
|
||||||
String identifier) throws GuacamoleException {
|
String identifier) throws GuacamoleException {
|
||||||
|
|
||||||
// Only administrators may retrieve active connections
|
// Pull objects having given identifier
|
||||||
if (!user.getUser().isAdministrator())
|
Collection<TrackedActiveConnection> objects = retrieveObjects(user, Collections.singleton(identifier));
|
||||||
throw new GuacamoleSecurityException("Permission denied.");
|
|
||||||
|
|
||||||
// Retrieve record associated with requested connection
|
// If no such object, return null
|
||||||
ActiveConnectionRecord record = tunnelService.getActiveConnection(user, identifier);
|
if (objects.isEmpty())
|
||||||
if (record == null)
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Return tracked active connection using retrieved record
|
// The object collection will have exactly one element unless the
|
||||||
TrackedActiveConnection activeConnection = trackedActiveConnectionProvider.get();
|
// database has seriously lost integrity
|
||||||
activeConnection.init(user, record);
|
assert(objects.size() == 1);
|
||||||
return activeConnection;
|
|
||||||
|
// Return first and only object
|
||||||
|
return objects.iterator().next();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<TrackedActiveConnection> retrieveObjects(AuthenticatedUser user,
|
public Collection<TrackedActiveConnection> retrieveObjects(AuthenticatedUser user,
|
||||||
Collection<String> identifiers) throws GuacamoleException {
|
Collection<String> identifiers) throws GuacamoleException {
|
||||||
|
|
||||||
// Build list of all active connections with given identifiers
|
boolean isAdmin = user.getUser().isAdministrator();
|
||||||
Collection<TrackedActiveConnection> activeConnections = new ArrayList<TrackedActiveConnection>(identifiers.size());
|
Set<String> identifierSet = new HashSet<String>(identifiers);
|
||||||
for (String identifier : identifiers) {
|
|
||||||
|
|
||||||
// Add connection to list if it exists
|
// Retrieve all visible connections (permissions enforced by tunnel service)
|
||||||
TrackedActiveConnection activeConnection = retrieveObject(user, identifier);
|
Collection<ActiveConnectionRecord> records = tunnelService.getActiveConnections(user);
|
||||||
if (activeConnection != null)
|
|
||||||
|
// Restrict to subset of records which match given identifiers
|
||||||
|
Collection<TrackedActiveConnection> activeConnections = new ArrayList<TrackedActiveConnection>(identifiers.size());
|
||||||
|
for (ActiveConnectionRecord record : records) {
|
||||||
|
|
||||||
|
// Add connection if within requested identifiers
|
||||||
|
if (identifierSet.contains(record.getUUID().toString())) {
|
||||||
|
TrackedActiveConnection activeConnection = trackedActiveConnectionProvider.get();
|
||||||
|
activeConnection.init(user, record, isAdmin);
|
||||||
activeConnections.add(activeConnection);
|
activeConnections.add(activeConnection);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return activeConnections;
|
return activeConnections;
|
||||||
@@ -101,6 +110,10 @@ public class ActiveConnectionService
|
|||||||
public void deleteObject(AuthenticatedUser user, String identifier)
|
public void deleteObject(AuthenticatedUser user, String identifier)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Only administrators may delete active connections
|
||||||
|
if (!user.getUser().isAdministrator())
|
||||||
|
throw new GuacamoleSecurityException("Permission denied.");
|
||||||
|
|
||||||
// Close connection, if it exists (and we have permission)
|
// Close connection, if it exists (and we have permission)
|
||||||
ActiveConnection activeConnection = retrieveObject(user, identifier);
|
ActiveConnection activeConnection = retrieveObject(user, identifier);
|
||||||
if (activeConnection != null) {
|
if (activeConnection != null) {
|
||||||
|
@@ -69,26 +69,40 @@ public class TrackedActiveConnection extends RestrictedObject implements ActiveC
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes this TrackedActiveConnection, copying the data associated
|
* Initializes this TrackedActiveConnection, copying the data associated
|
||||||
* with the given active connection record.
|
* with the given active connection record. At a minimum, the identifier
|
||||||
|
* of this active connection will be set, the start date, and the
|
||||||
|
* identifier of the associated connection will be copied. If requested,
|
||||||
|
* sensitive information like the associated username will be copied, as
|
||||||
|
* well.
|
||||||
*
|
*
|
||||||
* @param currentUser
|
* @param currentUser
|
||||||
* The user that created or retrieved this object.
|
* The user that created or retrieved this object.
|
||||||
*
|
*
|
||||||
* @param activeConnectionRecord
|
* @param activeConnectionRecord
|
||||||
* The active connection record to copy.
|
* The active connection record to copy.
|
||||||
|
*
|
||||||
|
* @param includeSensitiveInformation
|
||||||
|
* Whether sensitive data should be copied from the connection record
|
||||||
|
* as well. This includes the remote host, associated tunnel, and
|
||||||
|
* username.
|
||||||
*/
|
*/
|
||||||
public void init(AuthenticatedUser currentUser,
|
public void init(AuthenticatedUser currentUser,
|
||||||
ActiveConnectionRecord activeConnectionRecord) {
|
ActiveConnectionRecord activeConnectionRecord,
|
||||||
|
boolean includeSensitiveInformation) {
|
||||||
|
|
||||||
super.init(currentUser);
|
super.init(currentUser);
|
||||||
|
|
||||||
// Copy all data from given record
|
// Copy all non-sensitive data from given record
|
||||||
this.connectionIdentifier = activeConnectionRecord.getConnection().getIdentifier();
|
this.connectionIdentifier = activeConnectionRecord.getConnection().getIdentifier();
|
||||||
this.identifier = activeConnectionRecord.getUUID().toString();
|
this.identifier = activeConnectionRecord.getUUID().toString();
|
||||||
this.remoteHost = activeConnectionRecord.getRemoteHost();
|
|
||||||
this.startDate = activeConnectionRecord.getStartDate();
|
this.startDate = activeConnectionRecord.getStartDate();
|
||||||
this.tunnel = activeConnectionRecord.getTunnel();
|
|
||||||
this.username = activeConnectionRecord.getUsername();
|
// Include sensitive data, too, if requested
|
||||||
|
if (includeSensitiveInformation) {
|
||||||
|
this.remoteHost = activeConnectionRecord.getRemoteHost();
|
||||||
|
this.tunnel = activeConnectionRecord.getTunnel();
|
||||||
|
this.username = activeConnectionRecord.getUsername();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -28,8 +28,10 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||||
@@ -448,24 +450,33 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
|
|||||||
public Collection<ActiveConnectionRecord> getActiveConnections(AuthenticatedUser user)
|
public Collection<ActiveConnectionRecord> getActiveConnections(AuthenticatedUser user)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
// Only administrators may see all active connections
|
// Simply return empty list if there are no active tunnels
|
||||||
if (!user.getUser().isAdministrator())
|
Collection<ActiveConnectionRecord> records = activeTunnels.values();
|
||||||
|
if (records.isEmpty())
|
||||||
return Collections.EMPTY_LIST;
|
return Collections.EMPTY_LIST;
|
||||||
|
|
||||||
return Collections.unmodifiableCollection(activeTunnels.values());
|
// Build set of all connection identifiers associated with active tunnels
|
||||||
|
Set<String> identifiers = new HashSet<String>(records.size());
|
||||||
|
for (ActiveConnectionRecord record : records)
|
||||||
|
identifiers.add(record.getConnection().getIdentifier());
|
||||||
|
|
||||||
}
|
// Produce collection of readable connection identifiers
|
||||||
|
Collection<ConnectionModel> connections = connectionMapper.selectReadable(user.getUser().getModel(), identifiers);
|
||||||
|
|
||||||
@Override
|
// Ensure set contains only identifiers of readable connections
|
||||||
public ActiveConnectionRecord getActiveConnection(AuthenticatedUser user,
|
identifiers.clear();
|
||||||
String tunnelUUID) throws GuacamoleException {
|
for (ConnectionModel connection : connections)
|
||||||
|
identifiers.add(connection.getIdentifier());
|
||||||
|
|
||||||
// Only administrators may see all active connections
|
// Produce readable subset of records
|
||||||
if (!user.getUser().isAdministrator())
|
Collection<ActiveConnectionRecord> visibleRecords = new ArrayList<ActiveConnectionRecord>(records.size());
|
||||||
return null;
|
for (ActiveConnectionRecord record : records) {
|
||||||
|
if (identifiers.contains(record.getConnection().getIdentifier()))
|
||||||
|
visibleRecords.add(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
return visibleRecords;
|
||||||
|
|
||||||
return activeTunnels.get(tunnelUUID);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -59,30 +59,6 @@ public interface GuacamoleTunnelService {
|
|||||||
public Collection<ActiveConnectionRecord> getActiveConnections(AuthenticatedUser user)
|
public Collection<ActiveConnectionRecord> getActiveConnections(AuthenticatedUser user)
|
||||||
throws GuacamoleException;
|
throws GuacamoleException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the connection records representing the connection associated
|
|
||||||
* with the tunnel having the given UUID, if that connection is visible to
|
|
||||||
* the given user.
|
|
||||||
*
|
|
||||||
* @param user
|
|
||||||
* The user retrieving the active connection.
|
|
||||||
*
|
|
||||||
* @param tunnelUUID
|
|
||||||
* The UUID of the tunnel associated with the active connection being
|
|
||||||
* retrieved.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The active connection associated with the tunnel having the given
|
|
||||||
* UUID, or null if no such connection exists.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while retrieving all active connections, or if
|
|
||||||
* permission is denied.
|
|
||||||
*/
|
|
||||||
public ActiveConnectionRecord getActiveConnection(AuthenticatedUser user,
|
|
||||||
String tunnelUUID)
|
|
||||||
throws GuacamoleException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a socket for the given user which connects to the given
|
* Creates a socket for the given user which connects to the given
|
||||||
* connection. The given client information will be passed to guacd when
|
* connection. The given client information will be passed to guacd when
|
||||||
|
@@ -34,7 +34,9 @@ import org.glyptodon.guacamole.net.GuacamoleTunnel;
|
|||||||
public interface ActiveConnection extends Identifiable {
|
public interface ActiveConnection extends Identifiable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the identifier of the connection being actively used.
|
* Returns the identifier of the connection being actively used. Unlike the
|
||||||
|
* other information stored in this object, the connection identifier must
|
||||||
|
* be present and MAY NOT be null.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* The identifier of the connection being actively used.
|
* The identifier of the connection being actively used.
|
||||||
@@ -53,7 +55,8 @@ public interface ActiveConnection extends Identifiable {
|
|||||||
* Returns the date and time the connection began.
|
* Returns the date and time the connection began.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* The date and time the connection began.
|
* The date and time the connection began, or null if this
|
||||||
|
* information is not available.
|
||||||
*/
|
*/
|
||||||
Date getStartDate();
|
Date getStartDate();
|
||||||
|
|
||||||
@@ -61,7 +64,8 @@ public interface ActiveConnection extends Identifiable {
|
|||||||
* Sets the date and time the connection began.
|
* Sets the date and time the connection began.
|
||||||
*
|
*
|
||||||
* @param startDate
|
* @param startDate
|
||||||
* The date and time the connection began.
|
* The date and time the connection began, or null if this
|
||||||
|
* information is not available.
|
||||||
*/
|
*/
|
||||||
void setStartDate(Date startDate);
|
void setStartDate(Date startDate);
|
||||||
|
|
||||||
@@ -90,7 +94,8 @@ public interface ActiveConnection extends Identifiable {
|
|||||||
* Returns the name of the user who is using this connection.
|
* Returns the name of the user who is using this connection.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* The name of the user who is using this connection.
|
* The name of the user who is using this connection, or null if this
|
||||||
|
* information is not available.
|
||||||
*/
|
*/
|
||||||
String getUsername();
|
String getUsername();
|
||||||
|
|
||||||
@@ -98,7 +103,8 @@ public interface ActiveConnection extends Identifiable {
|
|||||||
* Sets the name of the user who is using this connection.
|
* Sets the name of the user who is using this connection.
|
||||||
*
|
*
|
||||||
* @param username
|
* @param username
|
||||||
* The name of the user who is using this connection.
|
* The name of the user who is using this connection, or null if this
|
||||||
|
* information is not available.
|
||||||
*/
|
*/
|
||||||
void setUsername(String username);
|
void setUsername(String username);
|
||||||
|
|
||||||
|
@@ -106,14 +106,14 @@ public class ActiveConnectionRESTService {
|
|||||||
if (permissions != null && permissions.isEmpty())
|
if (permissions != null && permissions.isEmpty())
|
||||||
permissions = null;
|
permissions = null;
|
||||||
|
|
||||||
// An admin user has access to any user
|
// An admin user has access to any connection
|
||||||
SystemPermissionSet systemPermissions = self.getSystemPermissions();
|
SystemPermissionSet systemPermissions = self.getSystemPermissions();
|
||||||
boolean isAdmin = systemPermissions.hasPermission(SystemPermission.Type.ADMINISTER);
|
boolean isAdmin = systemPermissions.hasPermission(SystemPermission.Type.ADMINISTER);
|
||||||
|
|
||||||
// Get the directory
|
// Get the directory
|
||||||
Directory<ActiveConnection> activeConnectionDirectory = userContext.getActiveConnectionDirectory();
|
Directory<ActiveConnection> activeConnectionDirectory = userContext.getActiveConnectionDirectory();
|
||||||
|
|
||||||
// Filter users, if requested
|
// Filter connections, if requested
|
||||||
Collection<String> activeConnectionIdentifiers = activeConnectionDirectory.getIdentifiers();
|
Collection<String> activeConnectionIdentifiers = activeConnectionDirectory.getIdentifiers();
|
||||||
if (!isAdmin && permissions != null) {
|
if (!isAdmin && permissions != null) {
|
||||||
ObjectPermissionSet activeConnectionPermissions = self.getActiveConnectionPermissions();
|
ObjectPermissionSet activeConnectionPermissions = self.getActiveConnectionPermissions();
|
||||||
|
@@ -88,11 +88,58 @@ angular.module('groupList').directive('guacGroupList', [function guacGroupList()
|
|||||||
},
|
},
|
||||||
|
|
||||||
templateUrl: 'app/groupList/templates/guacGroupList.html',
|
templateUrl: 'app/groupList/templates/guacGroupList.html',
|
||||||
controller: ['$scope', '$injector', '$interval', function guacGroupListController($scope, $injector, $interval) {
|
controller: ['$scope', '$injector', function guacGroupListController($scope, $injector) {
|
||||||
|
|
||||||
// Get required types
|
// Required services
|
||||||
|
var activeConnectionService = $injector.get('activeConnectionService');
|
||||||
|
|
||||||
|
// Required types
|
||||||
var GroupListItem = $injector.get('GroupListItem');
|
var GroupListItem = $injector.get('GroupListItem');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of active connections associated with a given
|
||||||
|
* connection identifier. If this information is unknown, or there
|
||||||
|
* are no active connections for a given identifier, no number will
|
||||||
|
* be stored.
|
||||||
|
*
|
||||||
|
* @type Object.<String, Number>
|
||||||
|
*/
|
||||||
|
var connectionCount = {};
|
||||||
|
|
||||||
|
// Count active connections by connection identifier
|
||||||
|
activeConnectionService.getActiveConnections()
|
||||||
|
.success(function activeConnectionsRetrieved(activeConnections) {
|
||||||
|
|
||||||
|
// Count each active connection by identifier
|
||||||
|
angular.forEach(activeConnections, function addActiveConnection(activeConnection) {
|
||||||
|
|
||||||
|
// If counter already exists, increment
|
||||||
|
var identifier = activeConnection.connectionIdentifier;
|
||||||
|
if (connectionCount[identifier])
|
||||||
|
connectionCount[identifier]++;
|
||||||
|
|
||||||
|
// Otherwise, initialize counter to 1
|
||||||
|
else
|
||||||
|
connectionCount[identifier] = 1;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of active usages of a given connection.
|
||||||
|
*
|
||||||
|
* @param {Connection} connection
|
||||||
|
* The connection whose active connections should be counted.
|
||||||
|
*
|
||||||
|
* @returns {Number}
|
||||||
|
* The number of currently-active usages of the given
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
var countActiveConnections = function countActiveConnections(connection) {
|
||||||
|
return connectionCount[connection.identifier];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given item represents a connection that can
|
* Returns whether the given item represents a connection that can
|
||||||
* be displayed. If there is no connection template, then no
|
* be displayed. If there is no connection template, then no
|
||||||
@@ -131,7 +178,8 @@ angular.module('groupList').directive('guacGroupList', [function guacGroupList()
|
|||||||
if (connectionGroup) {
|
if (connectionGroup) {
|
||||||
|
|
||||||
// Create item hierarchy, including connections only if they will be visible
|
// Create item hierarchy, including connections only if they will be visible
|
||||||
var rootItem = GroupListItem.fromConnectionGroup(connectionGroup, !!$scope.connectionTemplate);
|
var rootItem = GroupListItem.fromConnectionGroup(connectionGroup,
|
||||||
|
!!$scope.connectionTemplate, countActiveConnections);
|
||||||
|
|
||||||
// If root group is to be shown, wrap that group as the child of a fake root group
|
// If root group is to be shown, wrap that group as the child of a fake root group
|
||||||
if ($scope.showRootGroup)
|
if ($scope.showRootGroup)
|
||||||
@@ -161,7 +209,7 @@ angular.module('groupList').directive('guacGroupList', [function guacGroupList()
|
|||||||
$scope.toggleExpanded = function toggleExpanded(groupListItem) {
|
$scope.toggleExpanded = function toggleExpanded(groupListItem) {
|
||||||
groupListItem.isExpanded = !groupListItem.isExpanded;
|
groupListItem.isExpanded = !groupListItem.isExpanded;
|
||||||
};
|
};
|
||||||
|
|
||||||
}]
|
}]
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@@ -102,12 +102,14 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
this.isExpanded = template.isExpanded;
|
this.isExpanded = template.isExpanded;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of currently active users for this connection or
|
* Returns the number of currently active users for this connection or
|
||||||
* connection group, if known.
|
* connection group, if known.
|
||||||
*
|
*
|
||||||
* @type Number
|
* @type Number
|
||||||
*/
|
*/
|
||||||
this.activeConnections = template.activeConnections;
|
this.getActiveConnections = template.getActiveConnections || (function getActiveConnections() {
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The connection or connection group whose data is exposed within
|
* The connection or connection group whose data is exposed within
|
||||||
@@ -126,10 +128,15 @@ 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 {Function} [countActiveConnections]
|
||||||
|
* A getter which returns the current number of active connections for
|
||||||
|
* the given connection. If omitted, the number of active connections
|
||||||
|
* known at the time this function was called is used instead.
|
||||||
|
*
|
||||||
* @returns {GroupListItem}
|
* @returns {GroupListItem}
|
||||||
* A new GroupListItem which represents the given connection.
|
* A new GroupListItem which represents the given connection.
|
||||||
*/
|
*/
|
||||||
GroupListItem.fromConnection = function fromConnection(connection) {
|
GroupListItem.fromConnection = function fromConnection(connection, countActiveConnections) {
|
||||||
|
|
||||||
// Return item representing the given connection
|
// Return item representing the given connection
|
||||||
return new GroupListItem({
|
return new GroupListItem({
|
||||||
@@ -144,7 +151,15 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
isConnectionGroup : false,
|
isConnectionGroup : false,
|
||||||
|
|
||||||
// Count of currently active connections using this connection
|
// Count of currently active connections using this connection
|
||||||
activeConnections : connection.activeConnections,
|
getActiveConnections : function getActiveConnections() {
|
||||||
|
|
||||||
|
// Use getter, if provided
|
||||||
|
if (countActiveConnections)
|
||||||
|
return countActiveConnections(connection);
|
||||||
|
|
||||||
|
return connection.activeConnections;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
// Wrapped item
|
// Wrapped item
|
||||||
wrappedItem : connection
|
wrappedItem : connection
|
||||||
@@ -165,26 +180,37 @@ 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 {Function} [countActiveConnections]
|
||||||
|
* A getter which returns the current number of active connections for
|
||||||
|
* the given connection. If omitted, the number of active connections
|
||||||
|
* known at the time this function was called is used instead.
|
||||||
|
*
|
||||||
|
* @param {Function} [countActiveConnectionGroups]
|
||||||
|
* A getter which returns the current number of active connections for
|
||||||
|
* the given connection group. If omitted, the number of active
|
||||||
|
* connections known at the time this function was called is used
|
||||||
|
* instead.
|
||||||
|
*
|
||||||
* @returns {GroupListItem}
|
* @returns {GroupListItem}
|
||||||
* A new GroupListItem which represents the given connection group,
|
* A new GroupListItem which represents the given connection group,
|
||||||
* including all descendants.
|
* including all descendants.
|
||||||
*/
|
*/
|
||||||
GroupListItem.fromConnectionGroup = function fromConnectionGroup(connectionGroup,
|
GroupListItem.fromConnectionGroup = function fromConnectionGroup(connectionGroup,
|
||||||
includeConnections) {
|
includeConnections, countActiveConnections, countActiveConnectionGroups) {
|
||||||
|
|
||||||
var children = [];
|
var children = [];
|
||||||
|
|
||||||
// Add any child connections
|
// Add any child connections
|
||||||
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(child));
|
children.push(GroupListItem.fromConnection(child, countActiveConnections));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add any child groups
|
// Add any child groups
|
||||||
if (connectionGroup.childConnectionGroups) {
|
if (connectionGroup.childConnectionGroups) {
|
||||||
connectionGroup.childConnectionGroups.forEach(function addChildGroup(child) {
|
connectionGroup.childConnectionGroups.forEach(function addChildGroup(child) {
|
||||||
children.push(GroupListItem.fromConnectionGroup(child, includeConnections));
|
children.push(GroupListItem.fromConnectionGroup(child, includeConnections, countActiveConnections, countActiveConnectionGroups));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +230,16 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio
|
|||||||
children : children,
|
children : children,
|
||||||
|
|
||||||
// Count of currently active connection groups using this connection
|
// Count of currently active connection groups using this connection
|
||||||
activeConnections : connectionGroup.activeConnections,
|
getActiveConnections : function getActiveConnections() {
|
||||||
|
|
||||||
|
// Use getter, if provided
|
||||||
|
if (countActiveConnectionGroups)
|
||||||
|
return countActiveConnectionGroups(connectionGroup);
|
||||||
|
|
||||||
|
return connectionGroup.activeConnections;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
// Wrapped item
|
// Wrapped item
|
||||||
wrappedItem : connectionGroup
|
wrappedItem : connectionGroup
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="caption" ng-class="{active: item.activeConnections}">
|
<div class="caption" ng-class="{active: item.getActiveConnections()}">
|
||||||
|
|
||||||
<!-- Connection icon -->
|
<!-- Connection icon -->
|
||||||
<div class="protocol">
|
<div class="protocol">
|
||||||
@@ -32,8 +32,8 @@
|
|||||||
<span class="name">{{item.name}}</span>
|
<span class="name">{{item.name}}</span>
|
||||||
|
|
||||||
<!-- Active user count -->
|
<!-- Active user count -->
|
||||||
<span class="activeUserCount" ng-show="item.activeConnections">
|
<span class="activeUserCount" ng-show="item.getActiveConnections()">
|
||||||
{{'HOME.INFO_ACTIVE_USER_COUNT' | translate:'{USERS: item.activeConnections}'}}
|
{{'HOME.INFO_ACTIVE_USER_COUNT' | translate:'{USERS: item.getActiveConnections()}'}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="caption" ng-class="{active: item.activeConnections}">
|
<div class="caption" ng-class="{active: item.getActiveConnections()}">
|
||||||
|
|
||||||
<!-- Connection icon -->
|
<!-- Connection icon -->
|
||||||
<div class="protocol">
|
<div class="protocol">
|
||||||
@@ -32,8 +32,8 @@
|
|||||||
<span class="name">{{item.name}}</span>
|
<span class="name">{{item.name}}</span>
|
||||||
|
|
||||||
<!-- Active user count -->
|
<!-- Active user count -->
|
||||||
<span class="activeUserCount" ng-show="item.activeConnections">
|
<span class="activeUserCount" ng-show="item.getActiveConnections()">
|
||||||
{{'MANAGE_CONNECTION.INFO_ACTIVE_USER_COUNT' | translate:'{USERS: item.activeConnections}'}}
|
{{'MANAGE_CONNECTION.INFO_ACTIVE_USER_COUNT' | translate:'{USERS: item.getActiveConnections()}'}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@@ -59,7 +59,7 @@ angular.module('rest').factory('ActiveConnection', [function defineActiveConnect
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The time that the connection began, in seconds since
|
* The time that the connection began, in seconds since
|
||||||
* 1970-01-01 00:00:00 UTC.
|
* 1970-01-01 00:00:00 UTC, if known.
|
||||||
*
|
*
|
||||||
* @type Number
|
* @type Number
|
||||||
*/
|
*/
|
||||||
@@ -73,7 +73,7 @@ angular.module('rest').factory('ActiveConnection', [function defineActiveConnect
|
|||||||
this.remoteHost = template.remoteHost;
|
this.remoteHost = template.remoteHost;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The username of the user associated with the connection.
|
* The username of the user associated with the connection, if known.
|
||||||
*
|
*
|
||||||
* @type String
|
* @type String
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user