mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
Merge pull request #28 from glyptodon/cleanup-angular
GUAC-932: Finish cleanup and restoration of feature set.
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.glyptodon.guacamole.net.basic.rest;
|
||||
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
|
||||
import org.glyptodon.guacamole.net.auth.Connection;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
import org.glyptodon.guacamole.net.auth.User;
|
||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
import org.glyptodon.guacamole.net.basic.rest.connectiongroup.APIConnectionGroup;
|
||||
|
||||
/**
|
||||
* Provides easy access and automatic error handling for retrieval of objects,
|
||||
* such as users, connections, or connection groups. REST API semantics, such
|
||||
* as the special root connection group identifier, are also handled
|
||||
* automatically.
|
||||
*/
|
||||
public class ObjectRetrievalService {
|
||||
|
||||
/**
|
||||
* Retrieves a single user from the given user context.
|
||||
*
|
||||
* @param userContext
|
||||
* The user context to retrieve the user from.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the user to retrieve.
|
||||
*
|
||||
* @return
|
||||
* The user having the given identifier.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the user, or if the
|
||||
* user does not exist.
|
||||
*/
|
||||
public User retrieveUser(UserContext userContext,
|
||||
String identifier) throws GuacamoleException {
|
||||
|
||||
// Get user directory
|
||||
Directory<String, User> directory = userContext.getUserDirectory();
|
||||
|
||||
// Pull specified user
|
||||
User user = directory.get(identifier);
|
||||
if (user == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such user: \"" + identifier + "\"");
|
||||
|
||||
return user;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a single connection from the given user context.
|
||||
*
|
||||
* @param userContext
|
||||
* The user context to retrieve the connection from.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the connection to retrieve.
|
||||
*
|
||||
* @return
|
||||
* The connection having the given identifier.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the connection, or if the
|
||||
* connection does not exist.
|
||||
*/
|
||||
public Connection retrieveConnection(UserContext userContext,
|
||||
String identifier) throws GuacamoleException {
|
||||
|
||||
// Get root directory
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
Directory<String, Connection> directory = rootGroup.getConnectionDirectory();
|
||||
|
||||
// Pull specified connection
|
||||
Connection connection = directory.get(identifier);
|
||||
if (connection == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection: \"" + identifier + "\"");
|
||||
|
||||
return connection;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a single connection group from the given user context. If
|
||||
* the given identifier the REST API root identifier, the root connection
|
||||
* group will be returned. The underlying authentication provider may
|
||||
* additionally use a different identifier for root.
|
||||
*
|
||||
* @param userContext
|
||||
* The user context to retrieve the connection group from.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the connection group to retrieve.
|
||||
*
|
||||
* @return
|
||||
* The connection group having the given identifier, or the root
|
||||
* connection group if the identifier the root identifier.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the connection group, or if the
|
||||
* connection group does not exist.
|
||||
*/
|
||||
public ConnectionGroup retrieveConnectionGroup(UserContext userContext,
|
||||
String identifier) throws GuacamoleException {
|
||||
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
// Use root group if identifier is null (or the standard root identifier)
|
||||
if (identifier != null && identifier.equals(APIConnectionGroup.ROOT_IDENTIFIER))
|
||||
return rootGroup;
|
||||
|
||||
// Pull specified connection group otherwise
|
||||
Directory<String, ConnectionGroup> directory = rootGroup.getConnectionGroupDirectory();
|
||||
ConnectionGroup connectionGroup = directory.get(identifier);
|
||||
|
||||
if (connectionGroup == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + identifier + "\"");
|
||||
|
||||
return connectionGroup;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -38,6 +38,7 @@ public class RESTModule extends AbstractModule {
|
||||
|
||||
// Bind generic low-level services
|
||||
bind(ProtocolRetrievalService.class);
|
||||
bind(ObjectRetrievalService.class);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -44,8 +44,8 @@ import org.glyptodon.guacamole.net.auth.ConnectionRecord;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
|
||||
import org.glyptodon.guacamole.net.basic.rest.ObjectRetrievalService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.connectiongroup.APIConnectionGroup;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -71,6 +71,12 @@ public class ConnectionRESTService {
|
||||
@Inject
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
/**
|
||||
* Service for convenient retrieval of objects.
|
||||
*/
|
||||
@Inject
|
||||
private ObjectRetrievalService retrievalService;
|
||||
|
||||
/**
|
||||
* Retrieves an individual connection.
|
||||
*
|
||||
@@ -95,17 +101,8 @@ public class ConnectionRESTService {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get the connection directory
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
Directory<String, Connection> connectionDirectory =
|
||||
rootGroup.getConnectionDirectory();
|
||||
|
||||
// Get the connection
|
||||
Connection connection = connectionDirectory.get(connectionID);
|
||||
if (connection == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection: \"" + connectionID + "\"");
|
||||
|
||||
return new APIConnection(connection);
|
||||
// Retrieve the requested connection
|
||||
return new APIConnection(retrievalService.retrieveConnection(userContext, connectionID));
|
||||
|
||||
}
|
||||
|
||||
@@ -138,10 +135,8 @@ public class ConnectionRESTService {
|
||||
Directory<String, Connection> connectionDirectory =
|
||||
rootGroup.getConnectionDirectory();
|
||||
|
||||
// Get the connection
|
||||
Connection connection = connectionDirectory.get(connectionID);
|
||||
if (connection == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection: \"" + connectionID + "\"");
|
||||
// Retrieve the requested connection
|
||||
Connection connection = retrievalService.retrieveConnection(userContext, connectionID);
|
||||
|
||||
// Retrieve connection configuration
|
||||
GuacamoleConfiguration config = connection.getConfiguration();
|
||||
@@ -181,11 +176,8 @@ public class ConnectionRESTService {
|
||||
Directory<String, Connection> connectionDirectory =
|
||||
rootGroup.getConnectionDirectory();
|
||||
|
||||
// Get the connection
|
||||
Connection connection = connectionDirectory.get(connectionID);
|
||||
if (connection == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection: \"" + connectionID + "\"");
|
||||
|
||||
// Retrieve the requested connection's history
|
||||
Connection connection = retrievalService.retrieveConnection(userContext, connectionID);
|
||||
return connection.getHistory();
|
||||
|
||||
}
|
||||
@@ -216,54 +208,11 @@ public class ConnectionRESTService {
|
||||
Directory<String, Connection> connectionDirectory =
|
||||
rootGroup.getConnectionDirectory();
|
||||
|
||||
// Make sure the connection is there before trying to delete
|
||||
if (connectionDirectory.get(connectionID) == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection: \"" + connectionID + "\"");
|
||||
|
||||
// Delete the connection
|
||||
// Delete the specified connection
|
||||
connectionDirectory.remove(connectionID);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a single connection group from the given user context. If
|
||||
* the given identifier is null or the root identifier, the root connection
|
||||
* group will be returned.
|
||||
*
|
||||
* @param userContext
|
||||
* The user context to retrieve the connection group from.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the connection group to retrieve.
|
||||
*
|
||||
* @return
|
||||
* The connection group having the given identifier, or the root
|
||||
* connection group if the identifier is null or the root identifier.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the connection group, or if the
|
||||
* connection group does not exist.
|
||||
*/
|
||||
private ConnectionGroup retrieveConnectionGroup(UserContext userContext,
|
||||
String identifier) throws GuacamoleException {
|
||||
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
// Use root group if identifier is null (or the standard root identifier)
|
||||
if (identifier == null || identifier.equals(APIConnectionGroup.ROOT_IDENTIFIER))
|
||||
return rootGroup;
|
||||
|
||||
// Pull specified connection group otherwise
|
||||
Directory<String, ConnectionGroup> directory = rootGroup.getConnectionGroupDirectory();
|
||||
ConnectionGroup connectionGroup = directory.get(identifier);
|
||||
|
||||
if (connectionGroup == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + identifier + "\"");
|
||||
|
||||
return connectionGroup;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new connection and returns the identifier of the new
|
||||
* connection.
|
||||
@@ -294,7 +243,7 @@ public class ConnectionRESTService {
|
||||
|
||||
// Retrieve parent group
|
||||
String parentID = connection.getParentIdentifier();
|
||||
ConnectionGroup parentConnectionGroup = retrieveConnectionGroup(userContext, parentID);
|
||||
ConnectionGroup parentConnectionGroup = retrievalService.retrieveConnectionGroup(userContext, parentID);
|
||||
|
||||
// Add the new connection
|
||||
Directory<String, Connection> connectionDirectory = parentConnectionGroup.getConnectionDirectory();
|
||||
@@ -340,12 +289,10 @@ public class ConnectionRESTService {
|
||||
Directory<String, Connection> connectionDirectory =
|
||||
rootGroup.getConnectionDirectory();
|
||||
|
||||
// Make sure the connection is there before trying to update
|
||||
Connection existingConnection = connectionDirectory.get(connectionID);
|
||||
if (existingConnection == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection: \"" + connectionID + "\"");
|
||||
|
||||
// Retrieve connection configuration
|
||||
// Retrieve connection to update
|
||||
Connection existingConnection = retrievalService.retrieveConnection(userContext, connectionID);
|
||||
|
||||
// Build updated configuration
|
||||
GuacamoleConfiguration config = new GuacamoleConfiguration();
|
||||
config.setProtocol(connection.getProtocol());
|
||||
config.setParameters(connection.getParameters());
|
||||
@@ -355,6 +302,10 @@ public class ConnectionRESTService {
|
||||
existingConnection.setName(connection.getName());
|
||||
connectionDirectory.update(existingConnection);
|
||||
|
||||
// Update connection parent
|
||||
ConnectionGroup updatedParentGroup = retrievalService.retrieveConnectionGroup(userContext, connection.getParentIdentifier());
|
||||
connectionDirectory.move(connectionID, updatedParentGroup.getConnectionDirectory());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -88,11 +88,7 @@ public class APIConnectionGroup {
|
||||
|
||||
this.identifier = connectionGroup.getIdentifier();
|
||||
this.parentIdentifier = connectionGroup.getParentIdentifier();
|
||||
|
||||
// Use the explicit ROOT group ID
|
||||
if (this.parentIdentifier == null)
|
||||
this.parentIdentifier = ROOT_IDENTIFIER;
|
||||
|
||||
|
||||
this.name = connectionGroup.getName();
|
||||
this.type = connectionGroup.getType();
|
||||
|
||||
|
@@ -46,6 +46,7 @@ import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
|
||||
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
|
||||
import org.glyptodon.guacamole.net.basic.rest.ObjectRetrievalService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.connection.APIConnection;
|
||||
import org.slf4j.Logger;
|
||||
@@ -72,6 +73,12 @@ public class ConnectionGroupRESTService {
|
||||
@Inject
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
/**
|
||||
* Service for convenient retrieval of objects.
|
||||
*/
|
||||
@Inject
|
||||
private ObjectRetrievalService retrievalService;
|
||||
|
||||
/**
|
||||
* Retrieves the given connection group from the user context, including
|
||||
* all descendant connections and groups if requested.
|
||||
@@ -105,24 +112,14 @@ public class ConnectionGroupRESTService {
|
||||
|
||||
User self = userContext.self();
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
|
||||
// Retrieve specified connection group
|
||||
ConnectionGroup connectionGroup;
|
||||
|
||||
// Use root group if requested
|
||||
if (identifier == null || identifier.equals(APIConnectionGroup.ROOT_IDENTIFIER))
|
||||
connectionGroup = rootGroup;
|
||||
|
||||
// Otherwise, query requested group using root group directory
|
||||
else {
|
||||
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory =
|
||||
rootGroup.getConnectionGroupDirectory();
|
||||
|
||||
// Get the connection group from root directory
|
||||
connectionGroup = connectionGroupDirectory.get(identifier);
|
||||
if (connectionGroup == null)
|
||||
return null;
|
||||
|
||||
try {
|
||||
connectionGroup = retrievalService.retrieveConnectionGroup(userContext, identifier);
|
||||
}
|
||||
catch (GuacamoleResourceNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Wrap queried connection group
|
||||
@@ -274,18 +271,9 @@ public class ConnectionGroupRESTService {
|
||||
|
||||
// Get the connection group directory
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
// Use the root group if it was asked for
|
||||
if (connectionGroupID != null && connectionGroupID.equals(APIConnectionGroup.ROOT_IDENTIFIER))
|
||||
connectionGroupID = rootGroup.getIdentifier();
|
||||
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory =
|
||||
rootGroup.getConnectionGroupDirectory();
|
||||
|
||||
// Make sure the connection is there before trying to delete
|
||||
if (connectionGroupDirectory.get(connectionGroupID) == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + connectionGroupID + "\"");
|
||||
|
||||
// Delete the connection group
|
||||
connectionGroupDirectory.remove(connectionGroupID);
|
||||
|
||||
@@ -321,22 +309,9 @@ public class ConnectionGroupRESTService {
|
||||
if (connectionGroup == null)
|
||||
throw new GuacamoleClientException("Connection group JSON must be submitted when creating connections groups.");
|
||||
|
||||
// Retrieve parent group
|
||||
String parentID = connectionGroup.getParentIdentifier();
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
// Use root group if no parent is specified
|
||||
ConnectionGroup parentConnectionGroup;
|
||||
if (parentID == null)
|
||||
parentConnectionGroup = rootGroup;
|
||||
|
||||
// Pull specified connection group otherwise
|
||||
else {
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory = rootGroup.getConnectionGroupDirectory();
|
||||
parentConnectionGroup = connectionGroupDirectory.get(parentID);
|
||||
|
||||
if (parentConnectionGroup == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + parentID + "\"");
|
||||
}
|
||||
ConnectionGroup parentConnectionGroup = retrievalService.retrieveConnectionGroup(userContext, parentID);
|
||||
|
||||
// Add the new connection group
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory = parentConnectionGroup.getConnectionGroupDirectory();
|
||||
@@ -378,22 +353,22 @@ public class ConnectionGroupRESTService {
|
||||
if (connectionGroup == null)
|
||||
throw new GuacamoleClientException("Connection group JSON must be submitted when updating connection groups.");
|
||||
|
||||
// Get the connection directory
|
||||
// Get the connection group directory
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
// Use the root group if it was asked for
|
||||
if (connectionGroupID != null && connectionGroupID.equals(APIConnectionGroup.ROOT_IDENTIFIER))
|
||||
connectionGroupID = rootGroup.getIdentifier();
|
||||
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory =
|
||||
rootGroup.getConnectionGroupDirectory();
|
||||
|
||||
// Make sure the connection group is there before trying to update
|
||||
if (connectionGroupDirectory.get(connectionGroupID) == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + connectionGroupID + "\"");
|
||||
|
||||
// Retrieve connection group to update
|
||||
ConnectionGroup existingConnectionGroup = connectionGroupDirectory.get(connectionGroupID);
|
||||
|
||||
// Update the connection group
|
||||
connectionGroupDirectory.update(new APIConnectionGroupWrapper(connectionGroup));
|
||||
existingConnectionGroup.setName(connectionGroup.getName());
|
||||
existingConnectionGroup.setType(connectionGroup.getType());
|
||||
connectionGroupDirectory.update(existingConnectionGroup);
|
||||
|
||||
// Update connection group parent
|
||||
ConnectionGroup updatedParentGroup = retrievalService.retrieveConnectionGroup(userContext, connectionGroup.getParentIdentifier());
|
||||
connectionGroupDirectory.move(connectionGroupID, updatedParentGroup.getConnectionGroupDirectory());
|
||||
|
||||
}
|
||||
|
||||
|
@@ -54,6 +54,7 @@ import static org.glyptodon.guacamole.net.basic.rest.APIPatch.Operation.add;
|
||||
import static org.glyptodon.guacamole.net.basic.rest.APIPatch.Operation.remove;
|
||||
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
|
||||
import org.glyptodon.guacamole.net.basic.rest.HTTPException;
|
||||
import org.glyptodon.guacamole.net.basic.rest.ObjectRetrievalService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.PATCH;
|
||||
import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.permission.APIPermissionSet;
|
||||
@@ -105,6 +106,12 @@ public class UserRESTService {
|
||||
@Inject
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
/**
|
||||
* Service for convenient retrieval of objects.
|
||||
*/
|
||||
@Inject
|
||||
private ObjectRetrievalService retrievalService;
|
||||
|
||||
/**
|
||||
* Gets a list of users in the system, filtering the returned list by the
|
||||
* given permission, if specified.
|
||||
@@ -177,15 +184,8 @@ public class UserRESTService {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get the directory
|
||||
Directory<String, User> userDirectory = userContext.getUserDirectory();
|
||||
|
||||
// Get the user
|
||||
User user = userDirectory.get(username);
|
||||
if (user == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such user: \"" + username + "\"");
|
||||
|
||||
// Return the user
|
||||
// Retrieve the requested user
|
||||
User user = retrievalService.retrieveUser(userContext, username);
|
||||
return new APIUser(user);
|
||||
|
||||
}
|
||||
@@ -254,9 +254,7 @@ public class UserRESTService {
|
||||
"Username in path does not match username provided JSON data.");
|
||||
|
||||
// Get the user
|
||||
User existingUser = userDirectory.get(username);
|
||||
if (existingUser == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such user: \"" + username + "\"");
|
||||
User existingUser = retrievalService.retrieveUser(userContext, username);
|
||||
|
||||
// Do not update the user password if no password was provided
|
||||
if (user.getPassword() != null)
|
||||
|
@@ -25,7 +25,9 @@
|
||||
|
||||
<!-- Connection -->
|
||||
<div class="connection" ng-show="item.isConnection">
|
||||
<ng-include src="connectionTemplate"/>
|
||||
<div class="caption">
|
||||
<ng-include src="connectionTemplate"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Connection group -->
|
||||
|
@@ -29,31 +29,49 @@ angular.module('index').config(['$routeProvider', '$locationProvider',
|
||||
// Disable HTML5 mode (use # for routing)
|
||||
$locationProvider.html5Mode(false);
|
||||
|
||||
$routeProvider.
|
||||
when('/', {
|
||||
$routeProvider
|
||||
.when('/', {
|
||||
title: 'application.title',
|
||||
bodyClassName: 'home',
|
||||
templateUrl: 'app/home/templates/home.html',
|
||||
controller: 'homeController'
|
||||
}).
|
||||
when('/manage/', {
|
||||
})
|
||||
.when('/manage/', {
|
||||
title: 'application.title',
|
||||
bodyClassName: 'manage',
|
||||
templateUrl: 'app/manage/templates/manage.html',
|
||||
controller: 'manageController'
|
||||
}).
|
||||
when('/login/', {
|
||||
})
|
||||
.when('/manage/connections/:id?', {
|
||||
title: 'application.title',
|
||||
bodyClassName: 'manage',
|
||||
templateUrl: 'app/manage/templates/manageConnection.html',
|
||||
controller: 'manageConnectionController'
|
||||
})
|
||||
.when('/manage/connectionGroups/:id?', {
|
||||
title: 'application.title',
|
||||
bodyClassName: 'manage',
|
||||
templateUrl: 'app/manage/templates/manageConnectionGroup.html',
|
||||
controller: 'manageConnectionGroupController'
|
||||
})
|
||||
.when('/manage/users/:id', {
|
||||
title: 'application.title',
|
||||
bodyClassName: 'manage',
|
||||
templateUrl: 'app/manage/templates/manageUser.html',
|
||||
controller: 'manageUserController'
|
||||
})
|
||||
.when('/login/', {
|
||||
title: 'application.title',
|
||||
bodyClassName: 'login',
|
||||
templateUrl: 'app/login/templates/login.html',
|
||||
controller: 'loginController'
|
||||
}).
|
||||
when('/client/:type/:id/:params?', {
|
||||
})
|
||||
.when('/client/:type/:id/:params?', {
|
||||
bodyClassName: 'client',
|
||||
templateUrl: 'app/client/templates/client.html',
|
||||
controller: 'clientController'
|
||||
}).
|
||||
otherwise({
|
||||
})
|
||||
.otherwise({
|
||||
redirectTo: '/'
|
||||
});
|
||||
}]);
|
||||
|
@@ -92,23 +92,6 @@
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.dialog .dropdown {
|
||||
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
margin-top: -1px;
|
||||
|
||||
width: 3in;
|
||||
max-height: 2in;
|
||||
overflow: auto;
|
||||
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
background: white;
|
||||
|
||||
font-size: 10pt;
|
||||
|
||||
}
|
||||
|
||||
.dialog .footer {
|
||||
text-align: center;
|
||||
}
|
||||
|
@@ -20,33 +20,33 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
.user,
|
||||
.group,
|
||||
.connection {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.user a,
|
||||
.connection a,
|
||||
.group a {
|
||||
text-decoration:none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.user a:hover,
|
||||
.connection a:hover,
|
||||
.group a:hover {
|
||||
text-decoration:none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.user a:visited,
|
||||
.connection a:visited,
|
||||
.group a:visited {
|
||||
text-decoration:none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.group .connection .bears {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.connection:hover {
|
||||
background: #CDA;
|
||||
}
|
||||
@@ -73,6 +73,10 @@ div.recent-connections .protocol {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.caption > * {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.caption .name {
|
||||
margin-left: 0.25em;
|
||||
}
|
@@ -72,8 +72,8 @@ h2 ~ h2 {
|
||||
}
|
||||
|
||||
div.section {
|
||||
margin: 0;
|
||||
padding: 1em;
|
||||
margin: 1em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The controller for the connection edit modal.
|
||||
*/
|
||||
angular.module('manage').controller('connectionEditModalController', ['$scope', '$injector',
|
||||
function connectionEditModalController($scope, $injector) {
|
||||
|
||||
var connectionEditModal = $injector.get('connectionEditModal');
|
||||
var connectionService = $injector.get('connectionService');
|
||||
var Connection = $injector.get('Connection');
|
||||
var HistoryEntryWrapper = $injector.get('HistoryEntryWrapper');
|
||||
|
||||
// Make a copy of the old connection so that we can copy over the changes when done
|
||||
var oldConnection = $scope.connection;
|
||||
|
||||
// Copy data into a new conection object in case the user doesn't want to save
|
||||
$scope.connection = new Connection($scope.connection);
|
||||
|
||||
var newConnection = !$scope.connection.identifier;
|
||||
|
||||
// Set it to VNC by default
|
||||
if(!$scope.connection.protocol)
|
||||
$scope.connection.protocol = "vnc";
|
||||
|
||||
$scope.historyEntryWrappers = [];
|
||||
|
||||
// Wrap all the history entries
|
||||
if (!newConnection) {
|
||||
connectionService.getConnectionHistory($scope.connection.identifier).success(function wrapHistoryEntries(historyEntries) {
|
||||
historyEntries.forEach(function wrapHistoryEntry(historyEntry) {
|
||||
$scope.historyEntryWrappers.push(new HistoryEntryWrapper(historyEntry));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the modal.
|
||||
*/
|
||||
$scope.close = function close() {
|
||||
connectionEditModal.deactivate();
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the connection and close the modal.
|
||||
*/
|
||||
$scope.save = function save() {
|
||||
connectionService.saveConnection($scope.connection).success(function successfullyUpdatedConnection() {
|
||||
|
||||
var oldParentID = oldConnection.parentIdentifier;
|
||||
var newParentID = $scope.connection.parentIdentifier;
|
||||
|
||||
// Copy the data back to the original model
|
||||
angular.extend(oldConnection, $scope.connection);
|
||||
|
||||
// We have to move this connection
|
||||
if(oldParentID !== newParentID)
|
||||
|
||||
// New connections are created by default in root - don't try to move it if it's already there.
|
||||
if(newConnection && newParentID === $scope.rootGroup.identifier) {
|
||||
$scope.moveItem($scope.connection, oldParentID, newParentID);
|
||||
} else {
|
||||
connectionService.moveConnection($scope.connection).then(function moveConnection() {
|
||||
$scope.moveItem($scope.connection, oldParentID, newParentID);
|
||||
});
|
||||
}
|
||||
|
||||
// Close the modal
|
||||
connectionEditModal.deactivate();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete the connection and close the modal.
|
||||
*/
|
||||
$scope['delete'] = function deleteConnection() {
|
||||
|
||||
// Nothing to delete if the connection is new
|
||||
var newConnection = !$scope.connection.identifier;
|
||||
if(newConnection) {
|
||||
// Close the modal
|
||||
connectionEditModal.deactivate();
|
||||
return;
|
||||
}
|
||||
|
||||
connectionService.deleteConnection($scope.connection).success(function successfullyDeletedConnection() {
|
||||
var oldParentID = oldConnection.parentIdentifier;
|
||||
|
||||
// We have to remove this connection from the heirarchy
|
||||
$scope.moveItem($scope.connection, oldParentID);
|
||||
|
||||
// Close the modal
|
||||
connectionEditModal.deactivate();
|
||||
});
|
||||
};
|
||||
|
||||
}]);
|
||||
|
||||
|
||||
|
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The controller for the connection group edit modal.
|
||||
*/
|
||||
angular.module('manage').controller('connectionGroupEditModalController', ['$scope', '$injector',
|
||||
function connectionEditModalController($scope, $injector) {
|
||||
|
||||
var connectionGroupEditModal = $injector.get('connectionGroupEditModal');
|
||||
var connectionGroupService = $injector.get('connectionGroupService');
|
||||
|
||||
// Make a copy of the old connection group so that we can copy over the changes when done
|
||||
var oldConnectionGroup = $scope.connectionGroup;
|
||||
|
||||
// Copy data into a new conection group object in case the user doesn't want to save
|
||||
$scope.connectionGroup = angular.copy($scope.connectionGroup);
|
||||
|
||||
var newConnectionGroup = !$scope.connectionGroup.identifier;
|
||||
|
||||
$scope.types = [
|
||||
{
|
||||
label: "organizational",
|
||||
value: "ORGANIZATIONAL"
|
||||
},
|
||||
{
|
||||
label: "balancing",
|
||||
value: "BALANCING"
|
||||
}
|
||||
];
|
||||
|
||||
// Set it to organizational by default
|
||||
if(!$scope.connectionGroup.type)
|
||||
$scope.connectionGroup.type = $scope.types[0].value;
|
||||
|
||||
/**
|
||||
* Close the modal.
|
||||
*/
|
||||
$scope.close = function close() {
|
||||
connectionGroupEditModal.deactivate();
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the connection and close the modal.
|
||||
*/
|
||||
$scope.save = function save() {
|
||||
connectionGroupService.saveConnectionGroup($scope.connectionGroup).success(function successfullyUpdatedConnectionGroup() {
|
||||
|
||||
var oldParentID = oldConnectionGroup.parentIdentifier;
|
||||
var newParentID = $scope.connectionGroup.parentIdentifier;
|
||||
|
||||
// Copy the data back to the original model
|
||||
angular.extend(oldConnectionGroup, $scope.connectionGroup);
|
||||
|
||||
// New groups are created by default in root - don't try to move it if it's already there.
|
||||
if(newConnectionGroup && newParentID === $scope.rootGroup.identifier) {
|
||||
$scope.moveItem($scope.connectionGroup, oldParentID, newParentID);
|
||||
} else {
|
||||
connectionGroupService.moveConnectionGroup($scope.connectionGroup).then(function moveConnectionGroup() {
|
||||
$scope.moveItem($scope.connectionGroup, oldParentID, newParentID);
|
||||
});
|
||||
}
|
||||
|
||||
// Close the modal
|
||||
connectionGroupEditModal.deactivate();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete the connection and close the modal.
|
||||
*/
|
||||
$scope['delete'] = function deleteConnectionGroup() {
|
||||
|
||||
// Nothing to delete if the connection is new
|
||||
if(newConnectionGroup)
|
||||
// Close the modal
|
||||
connectionGroupEditModal.deactivate();
|
||||
|
||||
connectionGroupService.deleteConnectionGroup($scope.connectionGroup).success(function successfullyDeletedConnectionGroup() {
|
||||
var oldParentID = oldConnectionGroup.parentIdentifier;
|
||||
|
||||
// We have to remove this connection group from the heirarchy
|
||||
$scope.moveItem($scope.connectionGroup, oldParentID);
|
||||
|
||||
// Close the modal
|
||||
connectionGroupEditModal.deactivate();
|
||||
});
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
|
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The controller for editing or creating connections.
|
||||
*/
|
||||
angular.module('manage').controller('manageConnectionController', ['$scope', '$injector',
|
||||
function manageConnectionController($scope, $injector) {
|
||||
|
||||
// Required types
|
||||
var Connection = $injector.get('Connection');
|
||||
var ConnectionGroup = $injector.get('ConnectionGroup');
|
||||
var HistoryEntryWrapper = $injector.get('HistoryEntryWrapper');
|
||||
var PermissionSet = $injector.get('PermissionSet');
|
||||
|
||||
// Required services
|
||||
var $location = $injector.get('$location');
|
||||
var $routeParams = $injector.get('$routeParams');
|
||||
var connectionService = $injector.get('connectionService');
|
||||
var connectionGroupService = $injector.get('connectionGroupService');
|
||||
var protocolService = $injector.get('protocolService');
|
||||
|
||||
/**
|
||||
* An action to be provided along with the object sent to showStatus which
|
||||
* closes the currently-shown status dialog.
|
||||
*/
|
||||
var ACKNOWLEDGE_ACTION = {
|
||||
name : "manage.error.action.acknowledge",
|
||||
// Handle action
|
||||
callback : function acknowledgeCallback() {
|
||||
$scope.showStatus(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The identifier of the connection being edited. If a new connection is
|
||||
* being created, this will not be defined.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
var identifier = $routeParams.id;
|
||||
|
||||
// Pull connection group hierarchy
|
||||
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER, PermissionSet.ObjectPermissionType.UPDATE)
|
||||
.success(function connectionGroupReceived(rootGroup) {
|
||||
$scope.rootGroup = rootGroup;
|
||||
});
|
||||
|
||||
// Get protocol metadata
|
||||
protocolService.getProtocols().success(function protocolsReceived(protocols) {
|
||||
$scope.protocols = protocols;
|
||||
});
|
||||
|
||||
// If we are editing an existing connection, pull its data
|
||||
if (identifier) {
|
||||
|
||||
// Pull data from existing connection
|
||||
connectionService.getConnection(identifier).success(function connectionRetrieved(connection) {
|
||||
$scope.connection = connection;
|
||||
});
|
||||
|
||||
// Pull connection history
|
||||
connectionService.getConnectionHistory(identifier).success(function historyReceived(historyEntries) {
|
||||
|
||||
// Wrap all history entries for sake of display
|
||||
$scope.historyEntryWrappers = [];
|
||||
historyEntries.forEach(function wrapHistoryEntry(historyEntry) {
|
||||
$scope.historyEntryWrappers.push(new HistoryEntryWrapper(historyEntry));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Pull connection parameters
|
||||
connectionService.getConnectionParameters(identifier).success(function parametersReceived(parameters) {
|
||||
$scope.parameters = parameters;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// If we are creating a new connection, populate skeleton connection data
|
||||
else {
|
||||
$scope.connection = new Connection({ protocol: 'vnc' });
|
||||
$scope.historyEntryWrappers = [];
|
||||
$scope.parameters = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels all pending edits, returning to the management page.
|
||||
*/
|
||||
$scope.cancel = function cancel() {
|
||||
$location.path('/manage/');
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves the connection, creating a new connection or updating the existing
|
||||
* connection.
|
||||
*/
|
||||
$scope.saveConnection = function saveConnection() {
|
||||
|
||||
$scope.connection.parameters = $scope.parameters;
|
||||
|
||||
// Save the connection
|
||||
connectionService.saveConnection($scope.connection)
|
||||
.success(function savedConnection() {
|
||||
$location.path('/manage/');
|
||||
})
|
||||
|
||||
// Notify of any errors
|
||||
.error(function connectionSaveFailed(error) {
|
||||
$scope.showStatus({
|
||||
'className' : 'error',
|
||||
'title' : 'manage.error.title',
|
||||
'text' : error.message,
|
||||
'actions' : [ ACKNOWLEDGE_ACTION ]
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* An action to be provided along with the object sent to showStatus which
|
||||
* immediately deletes the current connection.
|
||||
*/
|
||||
var DELETE_ACTION = {
|
||||
name : "manage.edit.connection.delete",
|
||||
className : "danger",
|
||||
// Handle action
|
||||
callback : function deleteCallback() {
|
||||
deleteConnectionImmediately();
|
||||
$scope.showStatus(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An action to be provided along with the object sent to showStatus which
|
||||
* closes the currently-shown status dialog.
|
||||
*/
|
||||
var CANCEL_ACTION = {
|
||||
name : "manage.edit.connection.cancel",
|
||||
// Handle action
|
||||
callback : function cancelCallback() {
|
||||
$scope.showStatus(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Immediately deletes the current connection, without prompting the user
|
||||
* for confirmation.
|
||||
*/
|
||||
var deleteConnectionImmediately = function deleteConnectionImmediately() {
|
||||
|
||||
// Delete the connection
|
||||
connectionService.deleteConnection($scope.connection)
|
||||
.success(function deletedConnection() {
|
||||
$location.path('/manage/');
|
||||
})
|
||||
|
||||
// Notify of any errors
|
||||
.error(function connectionDeletionFailed(error) {
|
||||
$scope.showStatus({
|
||||
'className' : 'error',
|
||||
'title' : 'manage.error.title',
|
||||
'text' : error.message,
|
||||
'actions' : [ ACKNOWLEDGE_ACTION ]
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the connection, prompting the user first to confirm that
|
||||
* deletion is desired.
|
||||
*/
|
||||
$scope.deleteConnection = function deleteConnection() {
|
||||
|
||||
// Confirm deletion request
|
||||
$scope.showStatus({
|
||||
'title' : 'manage.edit.connection.confirmDelete.title',
|
||||
'text' : 'manage.edit.connection.confirmDelete.text',
|
||||
'actions' : [ DELETE_ACTION, CANCEL_ACTION]
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
}]);
|
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The controller for editing or creating connection groups.
|
||||
*/
|
||||
angular.module('manage').controller('manageConnectionGroupController', ['$scope', '$injector',
|
||||
function manageConnectionGroupController($scope, $injector) {
|
||||
|
||||
// Required types
|
||||
var ConnectionGroup = $injector.get('ConnectionGroup');
|
||||
var PermissionSet = $injector.get('PermissionSet');
|
||||
|
||||
// Required services
|
||||
var $location = $injector.get('$location');
|
||||
var $routeParams = $injector.get('$routeParams');
|
||||
var connectionGroupService = $injector.get('connectionGroupService');
|
||||
|
||||
/**
|
||||
* An action to be provided along with the object sent to showStatus which
|
||||
* closes the currently-shown status dialog.
|
||||
*/
|
||||
var ACKNOWLEDGE_ACTION = {
|
||||
name : "manage.error.action.acknowledge",
|
||||
// Handle action
|
||||
callback : function acknowledgeCallback() {
|
||||
$scope.showStatus(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The identifier of the connection group being edited. If a new connection
|
||||
* group is being created, this will not be defined.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
var identifier = $routeParams.id;
|
||||
|
||||
// Pull connection group hierarchy
|
||||
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER, PermissionSet.ObjectPermissionType.UPDATE)
|
||||
.success(function connectionGroupReceived(rootGroup) {
|
||||
$scope.rootGroup = rootGroup;
|
||||
});
|
||||
|
||||
// If we are editing an existing connection group, pull its data
|
||||
if (identifier) {
|
||||
connectionGroupService.getConnectionGroup(identifier).success(function connectionGroupReceived(connectionGroup) {
|
||||
$scope.connectionGroup = connectionGroup;
|
||||
});
|
||||
}
|
||||
|
||||
// If we are creating a new connection group, populate skeleton connection group data
|
||||
else
|
||||
$scope.connectionGroup = new ConnectionGroup();
|
||||
|
||||
/**
|
||||
* Available connection group types, as translation string / internal value
|
||||
* pairs.
|
||||
*
|
||||
* @type Object[]
|
||||
*/
|
||||
$scope.types = [
|
||||
{
|
||||
label: "organizational",
|
||||
value: ConnectionGroup.Type.ORGANIZATIONAL
|
||||
},
|
||||
{
|
||||
label : "balancing",
|
||||
value : ConnectionGroup.Type.BALANCING
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* Cancels all pending edits, returning to the management page.
|
||||
*/
|
||||
$scope.cancel = function cancel() {
|
||||
$location.path('/manage/');
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves the connection group, creating a new connection group or updating
|
||||
* the existing connection group.
|
||||
*/
|
||||
$scope.saveConnectionGroup = function saveConnectionGroup() {
|
||||
|
||||
// Save the connection
|
||||
connectionGroupService.saveConnectionGroup($scope.connectionGroup)
|
||||
.success(function savedConnectionGroup() {
|
||||
$location.path('/manage/');
|
||||
})
|
||||
|
||||
// Notify of any errors
|
||||
.error(function connectionGroupSaveFailed(error) {
|
||||
$scope.showStatus({
|
||||
'className' : 'error',
|
||||
'title' : 'manage.error.title',
|
||||
'text' : error.message,
|
||||
'actions' : [ ACKNOWLEDGE_ACTION ]
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* An action to be provided along with the object sent to showStatus which
|
||||
* immediately deletes the current connection group.
|
||||
*/
|
||||
var DELETE_ACTION = {
|
||||
name : "manage.edit.connectionGroup.delete",
|
||||
className : "danger",
|
||||
// Handle action
|
||||
callback : function deleteCallback() {
|
||||
deleteConnectionGroupImmediately();
|
||||
$scope.showStatus(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An action to be provided along with the object sent to showStatus which
|
||||
* closes the currently-shown status dialog.
|
||||
*/
|
||||
var CANCEL_ACTION = {
|
||||
name : "manage.edit.connectionGroup.cancel",
|
||||
// Handle action
|
||||
callback : function cancelCallback() {
|
||||
$scope.showStatus(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Immediately deletes the current connection group, without prompting the
|
||||
* user for confirmation.
|
||||
*/
|
||||
var deleteConnectionGroupImmediately = function deleteConnectionGroupImmediately() {
|
||||
|
||||
// Delete the connection group
|
||||
connectionGroupService.deleteConnectionGroup($scope.connectionGroup)
|
||||
.success(function deletedConnectionGroup() {
|
||||
$location.path('/manage/');
|
||||
})
|
||||
|
||||
// Notify of any errors
|
||||
.error(function connectionGroupDeletionFailed(error) {
|
||||
$scope.showStatus({
|
||||
'className' : 'error',
|
||||
'title' : 'manage.error.title',
|
||||
'text' : error.message,
|
||||
'actions' : [ ACKNOWLEDGE_ACTION ]
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the connection group, prompting the user first to confirm that
|
||||
* deletion is desired.
|
||||
*/
|
||||
$scope.deleteConnectionGroup = function deleteConnectionGroup() {
|
||||
|
||||
// Confirm deletion request
|
||||
$scope.showStatus({
|
||||
'title' : 'manage.edit.connectionGroup.confirmDelete.title',
|
||||
'text' : 'manage.edit.connectionGroup.confirmDelete.text',
|
||||
'actions' : [ DELETE_ACTION, CANCEL_ACTION]
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
}]);
|
@@ -27,147 +27,78 @@ angular.module('manage').controller('manageController', ['$scope', '$injector',
|
||||
function manageController($scope, $injector) {
|
||||
|
||||
// Required types
|
||||
var PermissionSet = $injector.get('PermissionSet');
|
||||
var ConnectionGroup = $injector.get('ConnectionGroup');
|
||||
var PermissionSet = $injector.get('PermissionSet');
|
||||
var User = $injector.get('User');
|
||||
|
||||
// Required services
|
||||
var connectionGroupService = $injector.get('connectionGroupService');
|
||||
var connectionEditModal = $injector.get('connectionEditModal');
|
||||
var connectionGroupEditModal = $injector.get('connectionGroupEditModal');
|
||||
var userEditModal = $injector.get('userEditModal');
|
||||
var protocolService = $injector.get('protocolService');
|
||||
var userService = $injector.get('userService');
|
||||
|
||||
// Set status to loading until we have all the connections, groups, and users have loaded
|
||||
$scope.loadingUsers = true;
|
||||
$scope.loadingConnections = true;
|
||||
|
||||
$scope.basicPermissionsLoaded.then(function basicPermissionsHaveBeenLoaded() {
|
||||
var connectionGroupService = $injector.get('connectionGroupService');
|
||||
var userService = $injector.get('userService');
|
||||
|
||||
// Retrieve all users for whom we have UPDATE permission
|
||||
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER, PermissionSet.ObjectPermissionType.UPDATE)
|
||||
.success(function connectionGroupReceived(rootGroup) {
|
||||
$scope.rootGroup = rootGroup;
|
||||
$scope.loadingConnections = false;
|
||||
});
|
||||
|
||||
// Retrieve all users for whom we have UPDATE permission
|
||||
userService.getUsers(PermissionSet.ObjectPermissionType.UPDATE)
|
||||
.success(function usersReceived(users) {
|
||||
$scope.users = users;
|
||||
$scope.loadingUsers = false;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$scope.protocols = {};
|
||||
|
||||
// Get the protocol information from the server and copy it into the scope
|
||||
protocolService.getProtocols().success(function fetchProtocols(protocols) {
|
||||
$scope.protocols = protocols;
|
||||
});
|
||||
|
||||
// Expose object edit functions to group list template
|
||||
$scope.groupListContext = {
|
||||
|
||||
/**
|
||||
* Open a modal to edit the given connection.
|
||||
*
|
||||
* @param {Connection} connection
|
||||
* The connection to edit.
|
||||
*/
|
||||
editConnection : function editConnection(connection) {
|
||||
connectionEditModal.activate({
|
||||
connection : connection,
|
||||
protocols : $scope.protocols,
|
||||
rootGroup : $scope.rootGroup
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Open a modal to edit the given connection group.
|
||||
*
|
||||
* @param {ConnectionGroup} connectionGroup
|
||||
* The connection group to edit.
|
||||
*/
|
||||
editConnectionGroup : function editConnectionGroup(connectionGroup) {
|
||||
connectionGroupEditModal.activate({
|
||||
connectionGroup : connectionGroup,
|
||||
rootGroup : $scope.rootGroup
|
||||
});
|
||||
/**
|
||||
* An action to be provided along with the object sent to showStatus which
|
||||
* closes the currently-shown status dialog.
|
||||
*/
|
||||
var ACKNOWLEDGE_ACTION = {
|
||||
name : "manage.error.action.acknowledge",
|
||||
// Handle action
|
||||
callback : function acknowledgeCallback() {
|
||||
$scope.showStatus(false);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal to create a new connection.
|
||||
* The name of the new user to create, if any, when user creation is
|
||||
* requested via newUser().
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
$scope.newConnection = function newConnection() {
|
||||
connectionEditModal.activate(
|
||||
{
|
||||
connection : {},
|
||||
protocols : $scope.protocols,
|
||||
rootGroup : $scope.rootGroup
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal to create a new connection group.
|
||||
*/
|
||||
$scope.newConnectionGroup = function newConnectionGroup() {
|
||||
connectionGroupEditModal.activate(
|
||||
{
|
||||
connectionGroup : {},
|
||||
rootGroup : $scope.rootGroup
|
||||
});
|
||||
};
|
||||
|
||||
// Remove the user from the current list of users
|
||||
function removeUser(user) {
|
||||
for(var i = 0; i < $scope.users.length; i++) {
|
||||
if($scope.users[i].username === user.username) {
|
||||
$scope.users.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a modal to edit the user.
|
||||
*
|
||||
* @param {object} user The user to edit.
|
||||
*/
|
||||
$scope.editUser = function editUser(user) {
|
||||
userEditModal.activate(
|
||||
{
|
||||
user : user,
|
||||
rootGroup : $scope.rootGroup,
|
||||
removeUser : removeUser
|
||||
});
|
||||
};
|
||||
|
||||
$scope.newUsername = "";
|
||||
|
||||
// Retrieve all connections for which we have UPDATE permission
|
||||
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER, PermissionSet.ObjectPermissionType.UPDATE)
|
||||
.success(function connectionGroupReceived(rootGroup) {
|
||||
$scope.rootGroup = rootGroup;
|
||||
});
|
||||
|
||||
// Retrieve all users for whom we have UPDATE permission
|
||||
userService.getUsers(PermissionSet.ObjectPermissionType.UPDATE)
|
||||
.success(function usersReceived(users) {
|
||||
$scope.users = users;
|
||||
});
|
||||
|
||||
/**
|
||||
* Open a modal to edit the user.
|
||||
*
|
||||
* @param {object} user The user to edit.
|
||||
* Creates a new user having the username specified in the user creation
|
||||
* interface.
|
||||
*/
|
||||
$scope.newUser = function newUser() {
|
||||
if($scope.newUsername) {
|
||||
var newUser = {
|
||||
username: $scope.newUsername
|
||||
};
|
||||
|
||||
userService.createUser(newUser).success(function addUserToList() {
|
||||
$scope.users.push(newUser);
|
||||
|
||||
// Create user skeleton
|
||||
var user = new User({
|
||||
username: $scope.newUsername || ''
|
||||
});
|
||||
|
||||
// Create specified user
|
||||
userService.createUser(user)
|
||||
|
||||
// Add user to visible list upon success
|
||||
.success(function userCreated() {
|
||||
$scope.users.push(user);
|
||||
})
|
||||
|
||||
// Notify of any errors
|
||||
.error(function userCreationFailed(error) {
|
||||
$scope.showStatus({
|
||||
'className' : 'error',
|
||||
'title' : 'manage.error.title',
|
||||
'text' : error.message,
|
||||
'actions' : [ ACKNOWLEDGE_ACTION ]
|
||||
});
|
||||
|
||||
$scope.newUsername = "";
|
||||
}
|
||||
});
|
||||
|
||||
// Reset username
|
||||
$scope.newUsername = "";
|
||||
|
||||
};
|
||||
|
||||
}]);
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The controller for editing users.
|
||||
*/
|
||||
angular.module('manage').controller('manageUserController', ['$scope', '$injector',
|
||||
function manageUserController($scope, $injector) {
|
||||
|
||||
// Required types
|
||||
var ConnectionGroup = $injector.get('ConnectionGroup');
|
||||
var PermissionFlagSet = $injector.get('PermissionFlagSet');
|
||||
var PermissionSet = $injector.get('PermissionSet');
|
||||
|
||||
// Required services
|
||||
var $location = $injector.get('$location');
|
||||
var $routeParams = $injector.get('$routeParams');
|
||||
var connectionGroupService = $injector.get('connectionGroupService');
|
||||
var userService = $injector.get('userService');
|
||||
var permissionService = $injector.get('permissionService');
|
||||
|
||||
/**
|
||||
* An action to be provided along with the object sent to showStatus which
|
||||
* closes the currently-shown status dialog.
|
||||
*/
|
||||
var ACKNOWLEDGE_ACTION = {
|
||||
name : "manage.error.action.acknowledge",
|
||||
// Handle action
|
||||
callback : function acknowledgeCallback() {
|
||||
$scope.showStatus(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The username of the user being edited.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
var username = $routeParams.id;
|
||||
|
||||
// Pull user data
|
||||
userService.getUser(username).success(function userReceived(user) {
|
||||
$scope.user = user;
|
||||
});
|
||||
|
||||
// Pull user permissions
|
||||
permissionService.getPermissions(username).success(function gotPermissions(permissions) {
|
||||
$scope.permissionFlags = PermissionFlagSet.fromPermissionSet(permissions);
|
||||
});
|
||||
|
||||
// Retrieve all connections for which we have UPDATE permission
|
||||
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER, PermissionSet.ObjectPermissionType.ADMINISTER)
|
||||
.success(function connectionGroupReceived(rootGroup) {
|
||||
$scope.rootGroup = rootGroup;
|
||||
});
|
||||
|
||||
/**
|
||||
* Available system permission types, as translation string / internal
|
||||
* value pairs.
|
||||
*
|
||||
* @type Object[]
|
||||
*/
|
||||
$scope.systemPermissionTypes = [
|
||||
{
|
||||
label: "manage.edit.user.administerSystem",
|
||||
value: PermissionSet.SystemPermissionType.ADMINISTER
|
||||
},
|
||||
{
|
||||
label: "manage.edit.user.createUser",
|
||||
value: PermissionSet.SystemPermissionType.CREATE_USER
|
||||
},
|
||||
{
|
||||
label: "manage.edit.user.createConnection",
|
||||
value: PermissionSet.SystemPermissionType.CREATE_CONNECTION
|
||||
},
|
||||
{
|
||||
label: "manage.edit.user.createConnectionGroup",
|
||||
value: PermissionSet.SystemPermissionType.CREATE_CONNECTION_GROUP
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* The set of permissions that will be added to the user when the user is
|
||||
* saved. Permissions will only be present in this set if they are
|
||||
* manually added, and not later manually removed before saving.
|
||||
*
|
||||
* @type PermissionSet
|
||||
*/
|
||||
var permissionsAdded = new PermissionSet();
|
||||
|
||||
/**
|
||||
* The set of permissions that will be removed from the user when the user
|
||||
* is saved. Permissions will only be present in this set if they are
|
||||
* manually removed, and not later manually added before saving.
|
||||
*
|
||||
* @type PermissionSet
|
||||
*/
|
||||
var permissionsRemoved = new PermissionSet();
|
||||
|
||||
/**
|
||||
* Updates the permissionsAdded and permissionsRemoved permission sets to
|
||||
* reflect the addition of the given system permission.
|
||||
*
|
||||
* @param {String} type
|
||||
* The system permission to remove, as defined by
|
||||
* PermissionSet.SystemPermissionType.
|
||||
*/
|
||||
var addSystemPermission = function addSystemPermission(type) {
|
||||
|
||||
// If permission was previously removed, simply un-remove it
|
||||
if (PermissionSet.hasSystemPermission(permissionsRemoved, type))
|
||||
PermissionSet.removeSystemPermission(permissionsRemoved, type);
|
||||
|
||||
// Otherwise, explicitly add the permission
|
||||
else
|
||||
PermissionSet.addSystemPermission(permissionsAdded, type);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the permissionsAdded and permissionsRemoved permission sets to
|
||||
* reflect the removal of the given system permission.
|
||||
*
|
||||
* @param {String} type
|
||||
* The system permission to add, as defined by
|
||||
* PermissionSet.SystemPermissionType.
|
||||
*/
|
||||
var removeSystemPermission = function removeSystemPermission(type) {
|
||||
|
||||
// If permission was previously added, simply un-add it
|
||||
if (PermissionSet.hasSystemPermission(permissionsAdded, type))
|
||||
PermissionSet.removeSystemPermission(permissionsAdded, type);
|
||||
|
||||
// Otherwise, explicitly remove the permission
|
||||
else
|
||||
PermissionSet.addSystemPermission(permissionsRemoved, type);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies of a change to the selected system permissions for the user
|
||||
* being edited.
|
||||
*
|
||||
* @param {String} type
|
||||
* The system permission that was changed, as defined by
|
||||
* PermissionSet.SystemPermissionType.
|
||||
*/
|
||||
$scope.systemPermissionChanged = function systemPermissionChanged(type) {
|
||||
|
||||
// Determine current permission setting
|
||||
var value = $scope.permissionFlags.systemPermissions[type];
|
||||
|
||||
// Add/remove permission depending on flag state
|
||||
if (value)
|
||||
addSystemPermission(type);
|
||||
else
|
||||
removeSystemPermission(type);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the permissionsAdded and permissionsRemoved permission sets to
|
||||
* reflect the addition of the given connection permission.
|
||||
*
|
||||
* @param {String} identifier
|
||||
* The identifier of the connection to add READ permission for.
|
||||
*/
|
||||
var addConnectionPermission = function addConnectionPermission(identifier) {
|
||||
|
||||
// If permission was previously removed, simply un-remove it
|
||||
if (PermissionSet.hasConnectionPermission(permissionsRemoved, PermissionSet.ObjectPermissionType.READ, identifier))
|
||||
PermissionSet.removeConnectionPermission(permissionsRemoved, PermissionSet.ObjectPermissionType.READ, identifier);
|
||||
|
||||
// Otherwise, explicitly add the permission
|
||||
else
|
||||
PermissionSet.addConnectionPermission(permissionsAdded, PermissionSet.ObjectPermissionType.READ, identifier);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the permissionsAdded and permissionsRemoved permission sets to
|
||||
* reflect the removal of the given connection permission.
|
||||
*
|
||||
* @param {String} identifier
|
||||
* The identifier of the connection to remove READ permission for.
|
||||
*/
|
||||
var removeConnectionPermission = function removeConnectionPermission(identifier) {
|
||||
|
||||
// If permission was previously added, simply un-add it
|
||||
if (PermissionSet.hasConnectionPermission(permissionsAdded, PermissionSet.ObjectPermissionType.READ, identifier))
|
||||
PermissionSet.removeConnectionPermission(permissionsAdded, PermissionSet.ObjectPermissionType.READ, identifier);
|
||||
|
||||
// Otherwise, explicitly remove the permission
|
||||
else
|
||||
PermissionSet.addConnectionPermission(permissionsRemoved, PermissionSet.ObjectPermissionType.READ, identifier);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the permissionsAdded and permissionsRemoved permission sets to
|
||||
* reflect the addition of the given connection group permission.
|
||||
*
|
||||
* @param {String} identifier
|
||||
* The identifier of the connection group to add READ permission for.
|
||||
*/
|
||||
var addConnectionGroupPermission = function addConnectionGroupPermission(identifier) {
|
||||
|
||||
// If permission was previously removed, simply un-remove it
|
||||
if (PermissionSet.hasConnectionGroupPermission(permissionsRemoved, PermissionSet.ObjectPermissionType.READ, identifier))
|
||||
PermissionSet.removeConnectionGroupPermission(permissionsRemoved, PermissionSet.ObjectPermissionType.READ, identifier);
|
||||
|
||||
// Otherwise, explicitly add the permission
|
||||
else
|
||||
PermissionSet.addConnectionGroupPermission(permissionsAdded, PermissionSet.ObjectPermissionType.READ, identifier);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the permissionsAdded and permissionsRemoved permission sets to
|
||||
* reflect the removal of the given connection permission.
|
||||
*
|
||||
* @param {String} identifier
|
||||
* The identifier of the connection to remove READ permission for.
|
||||
*/
|
||||
var removeConnectionGroupPermission = function removeConnectionGroupPermission(identifier) {
|
||||
|
||||
// If permission was previously added, simply un-add it
|
||||
if (PermissionSet.hasConnectionGroupPermission(permissionsAdded, PermissionSet.ObjectPermissionType.READ, identifier))
|
||||
PermissionSet.removeConnectionGroupPermission(permissionsAdded, PermissionSet.ObjectPermissionType.READ, identifier);
|
||||
|
||||
// Otherwise, explicitly remove the permission
|
||||
else
|
||||
PermissionSet.addConnectionGroupPermission(permissionsRemoved, PermissionSet.ObjectPermissionType.READ, identifier);
|
||||
|
||||
};
|
||||
|
||||
// Expose permission query and modification functions to group list template
|
||||
$scope.groupListContext = {
|
||||
|
||||
/**
|
||||
* Returns the PermissionFlagSet that contains the current state of
|
||||
* granted permissions.
|
||||
*
|
||||
* @returns {PermissionFlagSet}
|
||||
* The PermissionFlagSet describing the current state of granted
|
||||
* permissions for the user being edited.
|
||||
*/
|
||||
getPermissionFlags : function getPermissionFlags() {
|
||||
return $scope.permissionFlags;
|
||||
},
|
||||
|
||||
/**
|
||||
* Notifies of a change to the selected connection permission for the
|
||||
* user being edited. This only applies to READ permissions.
|
||||
*
|
||||
* @param {String} identifier
|
||||
* The identifier of the connection affected by the changed
|
||||
* permission.
|
||||
*/
|
||||
connectionPermissionChanged : function connectionPermissionChanged(identifier) {
|
||||
|
||||
// Determine current permission setting
|
||||
var value = $scope.permissionFlags.connectionPermissions.READ[identifier];
|
||||
|
||||
// Add/remove permission depending on flag state
|
||||
if (value)
|
||||
addConnectionPermission(identifier);
|
||||
else
|
||||
removeConnectionPermission(identifier);
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Notifies of a change to the selected connection group permission for
|
||||
* the user being edited. This only applies to READ permissions.
|
||||
*
|
||||
* @param {String} identifier
|
||||
* The identifier of the connection group affected by the changed
|
||||
* permission.
|
||||
*/
|
||||
connectionGroupPermissionChanged : function connectionGroupPermissionChanged(identifier) {
|
||||
|
||||
// Determine current permission setting
|
||||
var value = $scope.permissionFlags.connectionGroupPermissions.READ[identifier];
|
||||
|
||||
// Add/remove permission depending on flag state
|
||||
if (value)
|
||||
addConnectionGroupPermission(identifier);
|
||||
else
|
||||
removeConnectionGroupPermission(identifier);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancels all pending edits, returning to the management page.
|
||||
*/
|
||||
$scope.cancel = function cancel() {
|
||||
$location.path('/manage/');
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves the user, updating the existing user only.
|
||||
*/
|
||||
$scope.saveUser = function saveUser() {
|
||||
|
||||
// Verify passwords match
|
||||
if ($scope.passwordMatch !== $scope.user.password) {
|
||||
$scope.showStatus({
|
||||
'className' : 'error',
|
||||
'title' : 'manage.error.title',
|
||||
'text' : 'manage.edit.user.passwordMismatch',
|
||||
'actions' : [ ACKNOWLEDGE_ACTION ]
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the user
|
||||
userService.saveUser($scope.user)
|
||||
.success(function savedUser() {
|
||||
|
||||
// Upon success, save any changed permissions
|
||||
permissionService.patchPermissions($scope.user.username, permissionsAdded, permissionsRemoved)
|
||||
.success(function patchedUserPermissions() {
|
||||
$location.path('/manage/');
|
||||
})
|
||||
|
||||
// Notify of any errors
|
||||
.error(function userPermissionsPatchFailed(error) {
|
||||
$scope.showStatus({
|
||||
'className' : 'error',
|
||||
'title' : 'manage.error.title',
|
||||
'text' : error.message,
|
||||
'actions' : [ ACKNOWLEDGE_ACTION ]
|
||||
});
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
// Notify of any errors
|
||||
.error(function userSaveFailed(error) {
|
||||
$scope.showStatus({
|
||||
'className' : 'error',
|
||||
'title' : 'manage.error.title',
|
||||
'text' : error.message,
|
||||
'actions' : [ ACKNOWLEDGE_ACTION ]
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* An action to be provided along with the object sent to showStatus which
|
||||
* immediately deletes the current user.
|
||||
*/
|
||||
var DELETE_ACTION = {
|
||||
name : "manage.edit.user.delete",
|
||||
className : "danger",
|
||||
// Handle action
|
||||
callback : function deleteCallback() {
|
||||
deleteUserImmediately();
|
||||
$scope.showStatus(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An action to be provided along with the object sent to showStatus which
|
||||
* closes the currently-shown status dialog.
|
||||
*/
|
||||
var CANCEL_ACTION = {
|
||||
name : "manage.edit.user.cancel",
|
||||
// Handle action
|
||||
callback : function cancelCallback() {
|
||||
$scope.showStatus(false);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Immediately deletes the current user, without prompting the user for
|
||||
* confirmation.
|
||||
*/
|
||||
var deleteUserImmediately = function deleteUserImmediately() {
|
||||
|
||||
// Delete the user
|
||||
userService.deleteUser($scope.user)
|
||||
.success(function deletedUser() {
|
||||
$location.path('/manage/');
|
||||
})
|
||||
|
||||
// Notify of any errors
|
||||
.error(function userDeletionFailed(error) {
|
||||
$scope.showStatus({
|
||||
'className' : 'error',
|
||||
'title' : 'manage.error.title',
|
||||
'text' : error.message,
|
||||
'actions' : [ ACKNOWLEDGE_ACTION ]
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the user, prompting the user first to confirm that deletion is
|
||||
* desired.
|
||||
*/
|
||||
$scope.deleteUser = function deleteUser() {
|
||||
|
||||
// Confirm deletion request
|
||||
$scope.showStatus({
|
||||
'title' : 'manage.edit.user.confirmDelete.title',
|
||||
'text' : 'manage.edit.user.confirmDelete.text',
|
||||
'actions' : [ DELETE_ACTION, CANCEL_ACTION]
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
}]);
|
@@ -1,263 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The controller for the connection edit modal.
|
||||
*/
|
||||
angular.module('manage').controller('userEditModalController', ['$scope', '$injector',
|
||||
function userEditModalController($scope, $injector) {
|
||||
|
||||
var userEditModal = $injector.get('userEditModal');
|
||||
var userService = $injector.get('userService');
|
||||
var permissionService = $injector.get('permissionService');
|
||||
|
||||
// Make a copy of the old user so that we can copy over the changes when done
|
||||
var oldUser = $scope.user;
|
||||
|
||||
// Copy data into a new conection object in case the user doesn't want to save
|
||||
$scope.user = angular.copy($scope.user);
|
||||
|
||||
/**
|
||||
* Close the modal.
|
||||
*/
|
||||
$scope.close = function close() {
|
||||
userEditModal.deactivate();
|
||||
};
|
||||
|
||||
/*
|
||||
* All the permissions that have been modified since this modal was opened.
|
||||
* Maps of type or id to value.
|
||||
*/
|
||||
$scope.modifiedSystemPermissions = {};
|
||||
$scope.modifiedConnectionPermissions = {};
|
||||
$scope.modifiedConnectionGroupPermissions = {};
|
||||
|
||||
$scope.markSystemPermissionModified = function markSystemPermissionModified(type) {
|
||||
$scope.modifiedSystemPermissions[type] = $scope.systemPermissions[type];
|
||||
};
|
||||
|
||||
$scope.markConnectionPermissionModified = function markConnectionPermissionModified(id) {
|
||||
$scope.modifiedConnectionPermissions[id] = $scope.connectionPermissions[id];
|
||||
};
|
||||
|
||||
$scope.markConnectionGroupPermissionModified = function markConnectionGroupPermissionModified(id) {
|
||||
$scope.modifiedConnectionGroupPermissions[id] = $scope.connectionGroupPermissions[id];
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the user and close the modal.
|
||||
*/
|
||||
$scope.save = function save() {
|
||||
|
||||
if($scope.passwordMatch !== $scope.user.password) {
|
||||
//TODO: Display an error
|
||||
return;
|
||||
}
|
||||
|
||||
userService.saveUser($scope.user).success(function successfullyUpdatedUser() {
|
||||
|
||||
//Figure out what permissions have changed
|
||||
var connectionPermissionsToCreate = [],
|
||||
connectionPermissionsToDelete = [],
|
||||
connectionGroupPermissionsToCreate = [],
|
||||
connectionGroupPermissionsToDelete = [],
|
||||
systemPermissionsToCreate = [],
|
||||
systemPermissionsToDelete = [];
|
||||
|
||||
for(var type in $scope.modifiedSystemPermissions) {
|
||||
// It was added
|
||||
if($scope.modifiedSystemPermissions[type] && !originalSystemPermissions[type]) {
|
||||
systemPermissionsToCreate.push(type);
|
||||
}
|
||||
// It was removed
|
||||
else if(!$scope.modifiedSystemPermissions[type] && originalSystemPermissions[type]) {
|
||||
systemPermissionsToDelete.push(type);
|
||||
}
|
||||
}
|
||||
|
||||
for(var id in $scope.modifiedConnectionPermissions) {
|
||||
// It was added
|
||||
if($scope.modifiedConnectionPermissions[id] && !originalConnectionPermissions[id]) {
|
||||
connectionPermissionsToCreate.push(id);
|
||||
}
|
||||
// It was removed
|
||||
else if(!$scope.modifiedConnectionPermissions[id] && originalConnectionPermissions[id]) {
|
||||
connectionPermissionsToDelete.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
for(var id in $scope.modifiedConnectionGroupPermissions) {
|
||||
// It was added
|
||||
if($scope.modifiedConnectionGroupPermissions[id] && !originalConnectionGroupPermissions[id]) {
|
||||
connectionGroupPermissionsToCreate.push(id);
|
||||
}
|
||||
// It was removed
|
||||
else if(!$scope.modifiedConnectionGroupPermissions[id] && originalConnectionGroupPermissions[id]) {
|
||||
connectionGroupPermissionsToDelete.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
var permissionsToAdd = [];
|
||||
var permissionsToRemove = [];
|
||||
|
||||
// Create new connection permissions
|
||||
for(var i = 0; i < connectionPermissionsToCreate.length; i++) {
|
||||
permissionsToAdd.push({
|
||||
objectType : "CONNECTION",
|
||||
objectIdentifier : connectionPermissionsToCreate[i],
|
||||
permissionType : "READ"
|
||||
});
|
||||
}
|
||||
|
||||
// Delete old connection permissions
|
||||
for(var i = 0; i < connectionPermissionsToDelete.length; i++) {
|
||||
permissionsToRemove.push({
|
||||
objectType : "CONNECTION",
|
||||
objectIdentifier : connectionPermissionsToDelete[i],
|
||||
permissionType : "READ"
|
||||
});
|
||||
}
|
||||
|
||||
// Create new connection group permissions
|
||||
for(var i = 0; i < connectionGroupPermissionsToCreate.length; i++) {
|
||||
permissionsToAdd.push({
|
||||
objectType : "CONNECTION_GROUP",
|
||||
objectIdentifier : connectionGroupPermissionsToCreate[i],
|
||||
permissionType : "READ"
|
||||
});
|
||||
}
|
||||
|
||||
// Delete old connection group permissions
|
||||
for(var i = 0; i < connectionGroupPermissionsToDelete.length; i++) {
|
||||
permissionsToRemove.push({
|
||||
objectType : "CONNECTION_GROUP",
|
||||
objectIdentifier : connectionGroupPermissionsToDelete[i],
|
||||
permissionType : "READ"
|
||||
});
|
||||
}
|
||||
|
||||
// Create new system permissions
|
||||
for(var i = 0; i < systemPermissionsToCreate.length; i++) {
|
||||
permissionsToAdd.push({
|
||||
objectType : "SYSTEM",
|
||||
permissionType : systemPermissionsToCreate[i]
|
||||
});
|
||||
}
|
||||
|
||||
// Delete old system permissions
|
||||
for(var i = 0; i < systemPermissionsToDelete.length; i++) {
|
||||
permissionsToRemove.push({
|
||||
objectType : "SYSTEM",
|
||||
permissionType : systemPermissionsToDelete[i]
|
||||
});
|
||||
}
|
||||
|
||||
function completeSaveProcess() {
|
||||
// Close the modal
|
||||
userEditModal.deactivate();
|
||||
}
|
||||
|
||||
function handleFailure() {
|
||||
//TODO: Handle the permission API call failure
|
||||
}
|
||||
|
||||
if(permissionsToAdd.length || permissionsToRemove.length) {
|
||||
// Make the call to update the permissions
|
||||
permissionService.patchPermissions(
|
||||
$scope.user.username, permissionsToAdd, permissionsToRemove)
|
||||
.success(completeSaveProcess).error(handleFailure);
|
||||
} else {
|
||||
completeSaveProcess();
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
$scope.permissions = [];
|
||||
|
||||
// Maps of connection and connection group IDs to access permission booleans
|
||||
$scope.connectionPermissions = {};
|
||||
$scope.connectionGroupPermissions = {};
|
||||
$scope.systemPermissions = {};
|
||||
|
||||
// The original permissions to compare against
|
||||
var originalConnectionPermissions,
|
||||
originalConnectionGroupPermissions,
|
||||
originalSystemPermissions;
|
||||
|
||||
// Get the permissions for the user we are editing
|
||||
permissionService.getPermissions($scope.user.username).success(function gotPermissions(permissions) {
|
||||
$scope.permissions = permissions;
|
||||
|
||||
// Figure out if the user has any system level permissions
|
||||
for(var i = 0; i < $scope.permissions.length; i++) {
|
||||
var permission = $scope.permissions[i];
|
||||
if(permission.objectType === "SYSTEM") {
|
||||
|
||||
$scope.systemPermissions[permission.permissionType] = true;
|
||||
|
||||
// Only READ permission is editable via this UI
|
||||
} else if (permission.permissionType === "READ") {
|
||||
switch(permission.objectType) {
|
||||
case "CONNECTION":
|
||||
$scope.connectionPermissions[permission.objectIdentifier] = true;
|
||||
break;
|
||||
case "CONNECTION_GROUP":
|
||||
$scope.connectionGroupPermissions[permission.objectIdentifier] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the original permissions so we can compare later
|
||||
originalConnectionPermissions = angular.copy($scope.connectionPermissions);
|
||||
originalConnectionGroupPermissions = angular.copy($scope.connectionGroupPermissions);
|
||||
originalSystemPermissions = angular.copy($scope.systemPermissions);
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* Delete the user and close the modal.
|
||||
*/
|
||||
$scope['delete'] = function deleteUser() {
|
||||
userService.deleteUser($scope.user).success(function successfullyDeletedUser() {
|
||||
|
||||
// Remove the user from the list
|
||||
$scope.removeUser($scope.user);
|
||||
|
||||
// Close the modal
|
||||
userEditModal.deactivate();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the open/closed status of the connectionGroup.
|
||||
*
|
||||
* @param {object} connectionGroup The connection group to toggle.
|
||||
*/
|
||||
$scope.toggleExpanded = function toggleExpanded(connectionGroup) {
|
||||
connectionGroup.expanded = !connectionGroup.expanded;
|
||||
};
|
||||
}]);
|
||||
|
||||
|
||||
|
@@ -31,55 +31,128 @@ angular.module('manage').directive('guacConnectionParameter', [function connecti
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
scope: {
|
||||
parameter: '=parameter',
|
||||
connection: '=connection',
|
||||
|
||||
/**
|
||||
* The protocol this parameter is associated with.
|
||||
*
|
||||
* @type Protocol
|
||||
*/
|
||||
protocol : '=',
|
||||
|
||||
/**
|
||||
* The unique name of this parameter within the protocol
|
||||
* definition.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
name : '=',
|
||||
|
||||
/**
|
||||
* The current map of parameter names to their corresponding string
|
||||
* values.
|
||||
*
|
||||
* @type Object.<String, String>
|
||||
*/
|
||||
parameters : '='
|
||||
|
||||
},
|
||||
templateUrl: 'app/manage/templates/connectionParameter.html',
|
||||
controller: ['$scope', function connectionParameterController($scope) {
|
||||
$scope.connectionParameters = $scope.connection.parameters;
|
||||
$scope.parameterType = $scope.parameter.type;
|
||||
$scope.parameterName = $scope.parameter.name;
|
||||
|
||||
// Coerce numeric strings to numbers
|
||||
if ($scope.parameterType === 'NUMERIC') {
|
||||
|
||||
// If a value exists, coerce it to a number
|
||||
if ($scope.connectionParameters[$scope.parameterName])
|
||||
$scope.parameterValue = Number($scope.connectionParameters[$scope.parameterName]);
|
||||
else
|
||||
$scope.parameterValue = null;
|
||||
|
||||
}
|
||||
|
||||
// Coerce boolean strings to boolean values
|
||||
else if ($scope.parameterType === 'BOOLEAN') {
|
||||
// TODO: Use defined checked value from protocol description
|
||||
$scope.parameterValue = $scope.connectionParameters[$scope.parameterName] === 'true';
|
||||
}
|
||||
|
||||
// All other parameter types are represented internally as strings
|
||||
else
|
||||
$scope.parameterValue = $scope.connectionParameters[$scope.parameterName];
|
||||
|
||||
// Update internal representation as model is changed
|
||||
$scope.$watch('parameterValue', function parameterValueChanges(value) {
|
||||
|
||||
// Convert numeric values back into strings
|
||||
if ($scope.parameterType === 'NUMERIC') {
|
||||
if (value === null || typeof value === 'undefined')
|
||||
$scope.connectionParameters[$scope.parameterName] = '';
|
||||
controller: ['$scope', '$q', function connectionParameterController($scope, $q) {
|
||||
|
||||
/**
|
||||
* Deferred load of the parameter definition, pending availability
|
||||
* of the protocol definition as a whole.
|
||||
*
|
||||
* @type Deferred
|
||||
*/
|
||||
var parameterDefinitionAvailable = $q.defer();
|
||||
|
||||
/**
|
||||
* Populates the parameter definition on the scope as
|
||||
* <code>$scope.parameter</code> if both the parameter name and
|
||||
* protocol definition are available. If either are unavailable,
|
||||
* this function has no effect.
|
||||
*/
|
||||
var retrieveParameterDefinition = function retrieveParameterDefinition() {
|
||||
|
||||
// Both name and protocol are needed to retrieve the parameter definition
|
||||
if (!$scope.name || !$scope.protocol)
|
||||
return;
|
||||
|
||||
// Once protocol definition is available, locate parameter definition by name
|
||||
$scope.protocol.parameters.forEach(function findParameter(parameter) {
|
||||
if (parameter.name === $scope.name) {
|
||||
$scope.parameter = parameter;
|
||||
parameterDefinitionAvailable.resolve(parameter);
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// Load parameter definition once protocol definition is available.
|
||||
$scope.$watch('name', retrieveParameterDefinition);
|
||||
$scope.$watch('protocol', retrieveParameterDefinition);
|
||||
|
||||
// Update typed value when parameter set is changed
|
||||
$scope.$watch('parameters', function setParameters(parameters) {
|
||||
|
||||
// Don't bother if no parameters were provided
|
||||
if (!parameters)
|
||||
return;
|
||||
|
||||
// Wait for parameter definition
|
||||
parameterDefinitionAvailable.promise.then(function setTypedValue() {
|
||||
|
||||
// Pull parameter value
|
||||
var value = parameters[$scope.name];
|
||||
|
||||
// Coerce numeric strings to numbers
|
||||
if ($scope.parameter.type === 'NUMERIC')
|
||||
$scope.typedValue = (value ? Number(value) : null);
|
||||
|
||||
// Coerce boolean strings to boolean values
|
||||
else if ($scope.parameter.type === 'BOOLEAN')
|
||||
$scope.typedValue = (value === $scope.parameter.value);
|
||||
|
||||
// All other parameter types are represented internally as strings
|
||||
else
|
||||
$scope.connectionParameters[$scope.parameterName] = value.toString();
|
||||
}
|
||||
|
||||
// TODO: Transform BOOLEAN input fields back into strings based on protocol description
|
||||
|
||||
// All other parameter types are already strings
|
||||
else
|
||||
$scope.connectionParameters[$scope.parameterName] = value;
|
||||
|
||||
$scope.typedValue = value || '';
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}]
|
||||
|
||||
// Update string value in parameter set when typed value is changed
|
||||
$scope.$watch('typedValue', function typedValueChanged(typedValue) {
|
||||
|
||||
// Don't bother if there's nothing to set
|
||||
if (!$scope.parameters)
|
||||
return;
|
||||
|
||||
// Wait for parameter definition
|
||||
parameterDefinitionAvailable.promise.then(function setValue() {
|
||||
|
||||
// Convert numeric values back into strings
|
||||
if ($scope.parameter.type === 'NUMERIC') {
|
||||
if (!typedValue)
|
||||
$scope.parameters[$scope.name] = '';
|
||||
else
|
||||
$scope.parameters[$scope.name] = typedValue.toString();
|
||||
}
|
||||
|
||||
// Convert boolean values back into strings based on protocol description
|
||||
else if ($scope.parameter.type === 'BOOLEAN')
|
||||
$scope.parameters[$scope.name] = (typedValue ? $scope.parameter.value : '');
|
||||
|
||||
// All other parameter types are already strings
|
||||
else
|
||||
$scope.parameters[$scope.name] = typedValue || '';
|
||||
|
||||
});
|
||||
|
||||
}); // end watch typedValue
|
||||
|
||||
}] // end controller
|
||||
};
|
||||
|
||||
}]);
|
@@ -72,13 +72,6 @@ angular.module('manage').directive('locationChooser', [function locationChooser(
|
||||
|
||||
};
|
||||
|
||||
// Map all known groups
|
||||
mapConnectionGroups($scope.rootGroup);
|
||||
|
||||
// If no value is specified, default to the root identifier
|
||||
if (!$scope.value || !($scope.value in connectionGroups))
|
||||
$scope.value = $scope.rootGroup.identifier;
|
||||
|
||||
/**
|
||||
* Whether the group list menu is currently open.
|
||||
*
|
||||
@@ -92,7 +85,7 @@ angular.module('manage').directive('locationChooser', [function locationChooser(
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
$scope.chosenConnectionGroupName = connectionGroups[$scope.value].name;
|
||||
$scope.chosenConnectionGroupName = null;
|
||||
|
||||
/**
|
||||
* Toggle the current state of the menu listing connection groups.
|
||||
@@ -125,6 +118,24 @@ angular.module('manage').directive('locationChooser', [function locationChooser(
|
||||
|
||||
};
|
||||
|
||||
$scope.$watch('rootGroup', function setRootGroup(rootGroup) {
|
||||
|
||||
connectionGroups = {};
|
||||
|
||||
if (!rootGroup)
|
||||
return;
|
||||
|
||||
// Map all known groups
|
||||
mapConnectionGroups(rootGroup);
|
||||
|
||||
// If no value is specified, default to the root identifier
|
||||
if (!$scope.value || !($scope.value in connectionGroups))
|
||||
$scope.value = rootGroup.identifier;
|
||||
|
||||
$scope.chosenConnectionGroupName = connectionGroups[$scope.value].name;
|
||||
|
||||
});
|
||||
|
||||
}]
|
||||
};
|
||||
|
||||
|
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A modal for editing a connection group.
|
||||
*/
|
||||
angular.module('manage').factory('connectionGroupEditModal', ['btfModal',
|
||||
function connectionGroupEditModal(btfModal) {
|
||||
|
||||
// Create the modal object to be used later to actually create the modal
|
||||
return btfModal({
|
||||
controller: 'connectionGroupEditModalController',
|
||||
controllerAs: 'modal',
|
||||
templateUrl: 'app/manage/templates/editableConnectionGroup.html',
|
||||
});
|
||||
}]);
|
@@ -31,7 +31,7 @@ button.add-user {
|
||||
|
||||
}
|
||||
|
||||
button.add-connection {
|
||||
a.button.add-connection {
|
||||
|
||||
background-image: url('images/action-icons/guac-monitor-add.png');
|
||||
background-repeat: no-repeat;
|
||||
@@ -42,7 +42,7 @@ button.add-connection {
|
||||
|
||||
}
|
||||
|
||||
button.add-connection-group {
|
||||
a.button.add-connection-group {
|
||||
|
||||
background-image: url('images/action-icons/guac-group-add.png');
|
||||
background-repeat: no-repeat;
|
||||
|
@@ -20,16 +20,13 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A modal for editing a connection.
|
||||
*/
|
||||
angular.module('manage').factory('userEditModal', ['btfModal',
|
||||
function userEditModal(btfModal) {
|
||||
|
||||
// Create the modal object to be used later to actually create the modal
|
||||
return btfModal({
|
||||
controller: 'userEditModalController',
|
||||
controllerAs: 'modal',
|
||||
templateUrl: 'app/manage/templates/editableUser.html',
|
||||
});
|
||||
}]);
|
||||
.manage table.properties th {
|
||||
text-align: left;
|
||||
font-weight: normal;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.manage .action-buttons {
|
||||
text-align: center;
|
||||
margin-bottom: 1em;
|
||||
}
|
@@ -20,16 +20,19 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A modal for editing a connection.
|
||||
*/
|
||||
angular.module('manage').factory('connectionEditModal', ['btfModal',
|
||||
function connectionEditModal(btfModal) {
|
||||
|
||||
// Create the modal object to be used later to actually create the modal
|
||||
return btfModal({
|
||||
controller: 'connectionEditModalController',
|
||||
controllerAs: 'modal',
|
||||
templateUrl: 'app/manage/templates/editableConnection.html',
|
||||
});
|
||||
}]);
|
||||
.location-chooser .dropdown {
|
||||
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
margin-top: -1px;
|
||||
|
||||
width: 3in;
|
||||
max-height: 2in;
|
||||
overflow: auto;
|
||||
|
||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
||||
background: white;
|
||||
|
||||
font-size: 10pt;
|
||||
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
<div ng-click="context.editConnection(item.wrappedItem)">
|
||||
<a ng-href="#/manage/connections/{{item.identifier}}">
|
||||
<!--
|
||||
Copyright (C) 2014 Glyptodon LLC
|
||||
|
||||
@@ -21,15 +21,12 @@
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<div class="caption">
|
||||
|
||||
<!-- Connection icon -->
|
||||
<div class="protocol">
|
||||
<div class="icon type" ng-class="item.protocol"></div>
|
||||
</div>
|
||||
|
||||
<!-- Connection name -->
|
||||
<span class="name">{{item.name}}</span>
|
||||
|
||||
<!-- Connection icon -->
|
||||
<div class="protocol">
|
||||
<div class="icon type" ng-class="item.protocol"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Connection name -->
|
||||
<span class="name">{{item.name}}</span>
|
||||
|
||||
</a>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<span class="name" ng-click="context.editConnectionGroup(item.wrappedItem)">
|
||||
<a ng-href="#/manage/connectionGroups/{{item.identifier}}">
|
||||
<!--
|
||||
Copyright (C) 2014 Glyptodon LLC
|
||||
|
||||
@@ -21,5 +21,5 @@
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
{{item.name}}
|
||||
</span>
|
||||
<span class="name">{{item.name}}</span>
|
||||
</a>
|
||||
|
@@ -0,0 +1,28 @@
|
||||
<div class="choice">
|
||||
<!--
|
||||
Copyright (C) 2014 Glyptodon LLC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<input type="checkbox" ng-model="context.getPermissionFlags().connectionGroupPermissions.READ[item.identifier]"
|
||||
ng-change="context.connectionGroupPermissionChanged(item.identifier)"/>
|
||||
|
||||
<span class="name">{{item.name}}</span>
|
||||
</div>
|
@@ -20,10 +20,11 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
<input ng-show="parameterType === 'TEXT'" type="text" ng-model="parameterValue"/>
|
||||
<input ng-show="parameterType === 'NUMERIC'" type="number" ng-model="parameterValue"/>
|
||||
<input ng-show="parameterType === 'USERNAME'" type="text" ng-model="parameterValue"/>
|
||||
<input ng-show="parameterType === 'PASSWORD'" type="password" ng-model="parameterValue"/>
|
||||
<input ng-show="parameterType === 'BOOLEAN'" type="checkbox" ng-model="parameterValue"/>
|
||||
<select ng-show="parameterType === 'ENUM'" ng-model="parameterValue" ng-options="option.value as 'protocol.' + connection.protocol + '.parameters.' + parameter.name + '.options.' + (option.value || 'empty') | translate for option in parameter.options | orderBy: value"></select>
|
||||
|
||||
<input ng-show="parameter.type === 'TEXT'" type="text" ng-model="typedValue"/>
|
||||
<input ng-show="parameter.type === 'NUMERIC'" type="number" ng-model="typedValue"/>
|
||||
<input ng-show="parameter.type === 'USERNAME'" type="text" ng-model="typedValue"/>
|
||||
<input ng-show="parameter.type === 'PASSWORD'" type="password" ng-model="typedValue"/>
|
||||
<input ng-show="parameter.type === 'BOOLEAN'" type="checkbox" ng-model="typedValue"/>
|
||||
<select ng-show="parameter.type === 'ENUM'" ng-model="typedValue" ng-options="option.value as 'protocol.' + protocol.name + '.parameters.' + parameter.name + '.options.' + (option.value || 'empty') | translate for option in parameter.options | orderBy: value"></select>
|
||||
</span>
|
@@ -0,0 +1,36 @@
|
||||
<div class="choice">
|
||||
<!--
|
||||
Copyright (C) 2014 Glyptodon LLC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- Connection icon -->
|
||||
<div class="protocol">
|
||||
<div class="icon type" ng-class="item.protocol"></div>
|
||||
</div>
|
||||
|
||||
<!-- Checkbox -->
|
||||
<input type="checkbox" ng-model="context.getPermissionFlags().connectionPermissions.READ[item.identifier]"
|
||||
ng-change="context.connectionPermissionChanged(item.identifier)"/>
|
||||
|
||||
<!-- Connection name -->
|
||||
<span class="name">{{item.name}}</span>
|
||||
|
||||
</div>
|
@@ -1,117 +0,0 @@
|
||||
<!--
|
||||
Copyright 2014 Glyptodon LLC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
|
||||
<!-- Dialog container for the modal -->
|
||||
<div class="dialog-container">
|
||||
<div class="dialog edit">
|
||||
|
||||
<!-- Connection name -->
|
||||
<div class="header">
|
||||
<h2>{{connection.name}}</h2>
|
||||
</div>
|
||||
|
||||
<!-- Main connection edit section -->
|
||||
<div class="body">
|
||||
<div class="form">
|
||||
<div class="settings section">
|
||||
<dl>
|
||||
<dd>
|
||||
<table class="fields section">
|
||||
|
||||
<!-- Edit connection name -->
|
||||
<tr>
|
||||
<th>{{'manage.edit.connection.name' | translate}}</th>
|
||||
|
||||
<td><input type="text" ng-model="connection.name"/></td>
|
||||
</tr>
|
||||
|
||||
<!-- Edit connection location -->
|
||||
<tr>
|
||||
<th>{{'manage.edit.connection.location' | translate}}</th>
|
||||
|
||||
<td>
|
||||
<location-chooser value="connection.parentIdentifier" root-group="rootGroup"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!-- Edit connection protocol -->
|
||||
<tr>
|
||||
<th>{{'manage.edit.connection.protocol' | translate}}</th>
|
||||
<td>
|
||||
<select ng-model="connection.protocol" ng-options="name as 'protocol.' + protocol.name + '.label' | translate for (name, protocol) in protocols | orderBy: name"></select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<table class="fields section">
|
||||
|
||||
<!-- All the different possible editable field types -->
|
||||
<tr ng-repeat="parameter in protocols[connection.protocol].parameters">
|
||||
<th>{{'protocol.' + connection.protocol + '.parameters.' + parameter.name + '.label' | translate}}:</th>
|
||||
<td>
|
||||
<guac-connection-parameter parameter="parameter" connection="connection" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</dd>
|
||||
|
||||
<!-- History connection area -->
|
||||
<dt>{{'manage.edit.connection.history.usageHistory' | translate}}</dt>
|
||||
|
||||
<dd ng-hide="connection.history.length">
|
||||
<p>{{'manage.edit.connection.history.connectionNotUsed' | translate}}</p>
|
||||
</dd>
|
||||
|
||||
<!-- History connection list -->
|
||||
<dd ng-show="connection.history.length">
|
||||
<table class="history section">
|
||||
<tr>
|
||||
<th>{{'manage.edit.connection.history.username' | translate}}</th>
|
||||
<th>{{'manage.edit.connection.history.startTime' | translate}}</th>
|
||||
<th>{{'manage.edit.connection.history.duration' | translate}}</th>
|
||||
</tr>
|
||||
<tbody>
|
||||
<tr ng-repeat="wrapper in historyEntryWrappers">
|
||||
<td class="username">{{wrapper.entry.username}}</td>
|
||||
<td class="start">{{wrapper.entry.startDate | date:'short'}}</td>
|
||||
<td class="duration">{{wrapper.durationText | translate:"{VALUE: wrapper.duration.value, UNIT: wrapper.duration.unit}"}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Control buttons -->
|
||||
<div class="footer">
|
||||
<button ng-click="save()">{{'manage.edit.connection.save' | translate}}</button>
|
||||
<button ng-click="close()">{{'manage.edit.connection.cancel' | translate}}</button>
|
||||
<button ng-click="delete()" class="danger">{{'manage.edit.connection.delete' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -1,79 +0,0 @@
|
||||
<!--
|
||||
Copyright 2014 Glyptodon LLC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
|
||||
<!-- Dialog container for the modal -->
|
||||
<div class="dialog-container">
|
||||
<div class="dialog edit">
|
||||
|
||||
<!-- Connection group name -->
|
||||
<div class="header">
|
||||
<h2>{{connectionGroup.name}}</h2>
|
||||
</div>
|
||||
|
||||
<!-- Main connection group edit section -->
|
||||
<div class="body">
|
||||
<div class="form">
|
||||
<div class="settings section">
|
||||
<dl>
|
||||
<dd>
|
||||
<table class="fields section">
|
||||
|
||||
<!-- Edit connection group name -->
|
||||
<tr>
|
||||
<th>{{'manage.edit.connectionGroup.name' | translate}}</th>
|
||||
|
||||
<td><input type="text" ng-model="connectionGroup.name"/></td>
|
||||
</tr>
|
||||
|
||||
<!-- Edit connection group location -->
|
||||
<tr>
|
||||
<th>{{'manage.edit.connectionGroup.location' | translate}}</th>
|
||||
|
||||
<td>
|
||||
<location-chooser value="connectionGroup.parentIdentifier" root-group="rootGroup"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!-- Edit connection group type -->
|
||||
<tr>
|
||||
<th>{{'manage.edit.connectionGroup.type.label' | translate}}</th>
|
||||
<td>
|
||||
<select ng-model="connectionGroup.type" ng-options="type.value as 'manage.edit.connectionGroup.type.' + type.label | translate for type in types | orderBy: name"></select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Control buttons -->
|
||||
<div class="footer">
|
||||
<button ng-click="save()">{{'manage.edit.connectionGroup.save' | translate}}</button>
|
||||
<button ng-click="close()">{{'manage.edit.connectionGroup.cancel' | translate}}</button>
|
||||
<button ng-click="delete()" class="danger">{{'manage.edit.connectionGroup.delete' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -1,141 +0,0 @@
|
||||
<!--
|
||||
Copyright 2014 Glyptodon LLC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- Hierarchical connection and connection group permission selector -->
|
||||
<script type="text/ng-template" id="nestedUserPermissionEditGroup.html">
|
||||
|
||||
<!-- Connection -->
|
||||
<div class="choice" ng-show="item.isConnection">
|
||||
<input type="checkbox" ng-model="connectionPermissions[item.identifier]" ng-change="markConnectionPermissionModified(item.identifier)"/>
|
||||
<div class="connection list-item">
|
||||
<div class="caption">
|
||||
<div class="protocol">
|
||||
<div class="icon" ng-class="item.protocol"></div>
|
||||
</div><span class="name">{{item.name}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Connection group -->
|
||||
<div class="choice" ng-show="!item.isConnection">
|
||||
<input type="checkbox" ng-model="connectionGroupPermissions[item.identifier]" ng-change="markConnectionGroupPermissionModified(item.identifier)"/>
|
||||
|
||||
<div class="group empty list-item balancer">
|
||||
<div class="caption">
|
||||
<div class="icon group" ng-click="toggleExpanded(item)" ng-class="{expanded: item.expanded, empty: !item.children.length, balancer: item.balancer && !item.children.length}"></div>
|
||||
|
||||
<span class="name">{{item.name}}</span>
|
||||
</div>
|
||||
|
||||
<!-- Connection group children -->
|
||||
<div class="children" ng-show="item.expanded">
|
||||
<div ng-repeat="item in item.children | orderBy : 'name'" ng-include="'nestedUserPermissionEditGroup.html'">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</script>
|
||||
|
||||
<!-- User edit modal -->
|
||||
<div class="dialog-container">
|
||||
<div class="dialog edit">
|
||||
<div class="header">
|
||||
<h2>{{user.username}}</h2>
|
||||
</div>
|
||||
|
||||
<div class="body">
|
||||
<div class="form">
|
||||
<div class="settings section">
|
||||
<dl>
|
||||
|
||||
<!-- User properties section -->
|
||||
<dt>{{'manage.edit.user.properties' | translate}}</dt>
|
||||
|
||||
<dd>
|
||||
<table class="fields section">
|
||||
<tr>
|
||||
<th>{{'manage.edit.user.password' | translate}}</th>
|
||||
|
||||
<td><input ng-model="user.password" type="password" /></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>{{'manage.edit.user.passwordMatch' | translate}}</th>
|
||||
|
||||
<td><input ng-model="passwordMatch" type="password" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</dd>
|
||||
|
||||
<!-- System permissions section -->
|
||||
<dt>{{'manage.edit.user.permissions' | translate}}</dt>
|
||||
|
||||
<dd>
|
||||
<table class="permissions section">
|
||||
<tr>
|
||||
<th>{{'manage.edit.user.administerSystem' | translate}}</th>
|
||||
|
||||
<td><input type="checkbox" ng-model="systemPermissions.ADMINISTER" ng-change="markSystemPermissionModified('ADMINISTER')" /></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>{{'manage.edit.user.createUser' | translate}}</th>
|
||||
|
||||
<td><input type="checkbox" ng-model="systemPermissions.CREATE_USER" ng-change="markSystemPermissionModified('CREATE_USER')" /></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>{{'manage.edit.user.createConnection' | translate}}</th>
|
||||
|
||||
<td><input type="checkbox" ng-model="systemPermissions.CREATE_CONNECTION" ng-change="markSystemPermissionModified('CREATE_CONNECTION')" /></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>{{'manage.edit.user.createConnectionGroup' | translate}}</th>
|
||||
|
||||
<td><input type="checkbox" ng-model="systemPermissions.CREATE_CONNECTION_GROUP" ng-change="markSystemPermissionModified('CREATE_CONNECTION_GROUP')" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</dd>
|
||||
|
||||
<!-- Connection and connection group permission section -->
|
||||
<dt>{{'manage.edit.user.connections' | translate}}</dt>
|
||||
<dd>
|
||||
<div class="group-view">
|
||||
<div class="list">
|
||||
<div ng-repeat="item in rootGroup.children | orderBy : 'name'" ng-include="'nestedUserPermissionEditGroup.html'"></div>
|
||||
</div>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Form controls -->
|
||||
<div class="footer">
|
||||
<button ng-click="save()">{{'manage.edit.user.save' | translate}}</button>
|
||||
<button ng-click="close()">{{'manage.edit.user.cancel' | translate}}</button>
|
||||
<button ng-click="delete()" class="danger">{{'manage.edit.user.delete' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -1,4 +1,4 @@
|
||||
<div>
|
||||
<div class="location-chooser">
|
||||
<!--
|
||||
Copyright 2014 Glyptodon LLC.
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- Open the dropdown -->
|
||||
<!-- Chosen group name -->
|
||||
<div ng-click="toggleMenu()" class="location">{{chosenConnectionGroupName}}</div>
|
||||
|
||||
|
||||
<!-- Dropdown hierarchical menu of groups -->
|
||||
<div ng-show="menuOpen" class="dropdown">
|
||||
<guac-group-list
|
||||
context="groupListContext"
|
||||
@@ -32,4 +32,5 @@
|
||||
connection-group="rootGroup"
|
||||
connection-group-template="'app/manage/templates/locationChooserConnectionGroup.html'"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@@ -40,11 +40,11 @@ THE SOFTWARE.
|
||||
</div>
|
||||
|
||||
<!-- List of users this user has access to -->
|
||||
<div class="user-list" ng-class="{loading: loadingUsers}">
|
||||
<div ng-click="editUser(user)" ng-repeat="user in users | orderBy : 'username'" class="list-item">
|
||||
<div class="user-list" ng-class="{loading: !users}">
|
||||
<div ng-repeat="user in users | orderBy : 'username'" class="user list-item">
|
||||
<div class="caption">
|
||||
<div class="icon user"></div>
|
||||
<span class="name">{{user.username}}</span>
|
||||
<a class="name" ng-href="#/manage/users/{{user.username}}">{{user.username}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -57,14 +57,13 @@ THE SOFTWARE.
|
||||
|
||||
<!-- Control to create a new connection or group -->
|
||||
<div class="connection-add-form">
|
||||
<button ng-click="newConnection()" class="add-connection">{{'manage.newConnection' | translate}}</button>
|
||||
<button ng-click="newConnectionGroup()" class="add-connection-group">{{'manage.newGroup' | translate}}</button>
|
||||
<a class="add-connection button" href="#/manage/connections/">{{'manage.newConnection' | translate}}</a>
|
||||
<a class="add-connection-group button" href="#/manage/connectionGroups/">{{'manage.newGroup' | translate}}</a>
|
||||
</div>
|
||||
|
||||
<!-- List of connections and groups this user has access to -->
|
||||
<div class="connection-list" ng-class="{loading: loadingConnections}">
|
||||
<div class="connection-list" ng-class="{loading: !rootGroup}">
|
||||
<guac-group-list
|
||||
context="groupListContext"
|
||||
connection-group="rootGroup"
|
||||
connection-template="'app/manage/templates/connection.html'"
|
||||
connection-group-template="'app/manage/templates/connectionGroup.html'"/>
|
||||
|
@@ -0,0 +1,102 @@
|
||||
<!--
|
||||
Copyright 2014 Glyptodon LLC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<div class="logout-panel">
|
||||
<a class="back button" href="#/manage/">{{'manage.back' | translate}}</a>
|
||||
<a class="logout button" ng-click="logout()">{{'home.logout' | translate}}</a>
|
||||
</div>
|
||||
|
||||
<!-- Main property editor -->
|
||||
<h2>{{'manage.edit.connection.title' | translate}}</h2>
|
||||
<div class="section">
|
||||
<table class="properties">
|
||||
|
||||
<!-- Edit connection name -->
|
||||
<tr>
|
||||
<th>{{'manage.edit.connection.name' | translate}}</th>
|
||||
|
||||
<td><input type="text" ng-model="connection.name"/></td>
|
||||
</tr>
|
||||
|
||||
<!-- Edit connection location -->
|
||||
<tr>
|
||||
<th>{{'manage.edit.connection.location' | translate}}</th>
|
||||
|
||||
<td>
|
||||
<location-chooser value="connection.parentIdentifier" root-group="rootGroup"></location-chooser>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!-- Edit connection protocol -->
|
||||
<tr>
|
||||
<th>{{'manage.edit.connection.protocol' | translate}}</th>
|
||||
<td>
|
||||
<select ng-model="connection.protocol" ng-options="name as 'protocol.' + protocol.name + '.label' | translate for (name, protocol) in protocols | orderBy: name"></select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Connection parameters -->
|
||||
<h2>{{'manage.edit.connection.parameters' | translate}}</h2>
|
||||
<div class="section" ng-class="{loading: !parameters}">
|
||||
<table class="properties">
|
||||
|
||||
<!-- All the different possible editable field types -->
|
||||
<tr ng-repeat="parameter in protocols[connection.protocol].parameters">
|
||||
<th>{{'protocol.' + connection.protocol + '.parameters.' + parameter.name + '.label' | translate}}:</th>
|
||||
<td>
|
||||
<guac-connection-parameter protocol="protocols[connection.protocol]" name="parameter.name" parameters="parameters"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Form action buttons -->
|
||||
<div class="action-buttons">
|
||||
<button ng-click="saveConnection()">{{'manage.edit.connection.save' | translate}}</button>
|
||||
<button ng-click="cancel()">{{'manage.edit.connection.cancel' | translate}}</button>
|
||||
<button ng-click="deleteConnection()" class="danger">{{'manage.edit.connection.delete' | translate}}</button>
|
||||
</div>
|
||||
|
||||
<!-- Connection history -->
|
||||
<h2>{{'manage.edit.connection.history.usageHistory' | translate}}</h2>
|
||||
<div class="history section" ng-class="{loading: !historyEntryWrappers}">
|
||||
<p ng-hide="historyEntryWrappers.length">{{'manage.edit.connection.history.connectionNotUsed' | translate}}</p>
|
||||
<table ng-show="historyEntryWrappers.length">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{'manage.edit.connection.history.username' | translate}}</th>
|
||||
<th>{{'manage.edit.connection.history.startTime' | translate}}</th>
|
||||
<th>{{'manage.edit.connection.history.duration' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="wrapper in historyEntryWrappers">
|
||||
<td class="username">{{wrapper.entry.username}}</td>
|
||||
<td class="start">{{wrapper.entry.startDate | date:'short'}}</td>
|
||||
<td class="duration">{{wrapper.durationText | translate:"{VALUE: wrapper.duration.value, UNIT: wrapper.duration.unit}"}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
@@ -0,0 +1,65 @@
|
||||
<!--
|
||||
Copyright 2014 Glyptodon LLC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<div class="logout-panel">
|
||||
<a class="back button" href="#/manage/">{{'manage.back' | translate}}</a>
|
||||
<a class="logout button" ng-click="logout()">{{'home.logout' | translate}}</a>
|
||||
</div>
|
||||
|
||||
<!-- Main property editor -->
|
||||
<h2>{{'manage.edit.connectionGroup.title' | translate}}</h2>
|
||||
<div class="section">
|
||||
<table class="properties">
|
||||
|
||||
<!-- Edit connection group name -->
|
||||
<tr>
|
||||
<th>{{'manage.edit.connectionGroup.name' | translate}}</th>
|
||||
|
||||
<td><input type="text" ng-model="connectionGroup.name"/></td>
|
||||
</tr>
|
||||
|
||||
<!-- Edit connection group location -->
|
||||
<tr>
|
||||
<th>{{'manage.edit.connectionGroup.location' | translate}}</th>
|
||||
|
||||
<td>
|
||||
<location-chooser value="connectionGroup.parentIdentifier" root-group="rootGroup"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!-- Edit connection group type -->
|
||||
<tr>
|
||||
<th>{{'manage.edit.connectionGroup.type.label' | translate}}</th>
|
||||
<td>
|
||||
<select ng-model="connectionGroup.type" ng-options="type.value as 'manage.edit.connectionGroup.type.' + type.label | translate for type in types | orderBy: name"></select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Form action buttons -->
|
||||
<div class="action-buttons">
|
||||
<button ng-click="saveConnectionGroup()">{{'manage.edit.connectionGroup.save' | translate}}</button>
|
||||
<button ng-click="cancel()">{{'manage.edit.connectionGroup.cancel' | translate}}</button>
|
||||
<button ng-click="deleteConnectionGroup()" class="danger">{{'manage.edit.connectionGroup.delete' | translate}}</button>
|
||||
</div>
|
@@ -0,0 +1,77 @@
|
||||
<!--
|
||||
Copyright 2014 Glyptodon LLC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<div class="logout-panel">
|
||||
<a class="back button" href="#/manage/">{{'manage.back' | translate}}</a>
|
||||
<a class="logout button" ng-click="logout()">{{'home.logout' | translate}}</a>
|
||||
</div>
|
||||
|
||||
<!-- Main property editor -->
|
||||
<h2>{{'manage.edit.user.title' | translate}}</h2>
|
||||
<div class="section">
|
||||
<table class="properties">
|
||||
<tr>
|
||||
<th>{{'manage.edit.user.username' | translate}}</th>
|
||||
|
||||
<td>{{user.username}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{'manage.edit.user.password' | translate}}</th>
|
||||
|
||||
<td><input ng-model="user.password" type="password" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{'manage.edit.user.passwordMatch' | translate}}</th>
|
||||
|
||||
<td><input ng-model="passwordMatch" type="password" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- System permissions section -->
|
||||
<h2>{{'manage.edit.user.permissions' | translate}}</h2>
|
||||
<div class="section">
|
||||
<table class="properties">
|
||||
<tr ng-repeat="systemPermissionType in systemPermissionTypes">
|
||||
<th>{{systemPermissionType.label | translate}}</th>
|
||||
<td><input type="checkbox" ng-model="permissionFlags.systemPermissions[systemPermissionType.value]"
|
||||
ng-change="systemPermissionChanged(systemPermissionType.value)"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Connection and connection group permission section -->
|
||||
<h2>{{'manage.edit.user.connections' | translate}}</h2>
|
||||
<div class="section" ng-class="{loading: !rootGroup}">
|
||||
<guac-group-list
|
||||
context="groupListContext"
|
||||
connection-group="rootGroup"
|
||||
connection-template="'app/manage/templates/connectionPermission.html'"
|
||||
connection-group-template="'app/manage/templates/connectionGroupPermission.html'"/>
|
||||
</div>
|
||||
|
||||
<!-- Form action buttons -->
|
||||
<div class="action-buttons">
|
||||
<button ng-click="saveUser()">{{'manage.edit.user.save' | translate}}</button>
|
||||
<button ng-click="cancel()">{{'manage.edit.user.cancel' | translate}}</button>
|
||||
<button ng-click="deleteUser()" class="danger">{{'manage.edit.user.delete' | translate}}</button>
|
||||
</div>
|
@@ -41,7 +41,7 @@
|
||||
|
||||
<!-- Buttons -->
|
||||
<div ng-show="notification.actions.length" class="buttons">
|
||||
<button ng-repeat="action in notification.actions" ng-click="action.callback()">{{action.name | translate}}</button>
|
||||
<button ng-repeat="action in notification.actions" ng-click="action.callback()" ng-class="action.className">{{action.name | translate}}</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@@ -35,8 +35,11 @@ angular.module('notification').factory('NotificationAction', [function defineNot
|
||||
*
|
||||
* @param {Function} callback
|
||||
* The callback to call when the user elects to perform this action.
|
||||
*
|
||||
* @param {String} className
|
||||
* The CSS class to associate with this action, if any.
|
||||
*/
|
||||
var NotificationAction = function NotificationAction(name, callback) {
|
||||
var NotificationAction = function NotificationAction(name, callback, className) {
|
||||
|
||||
/**
|
||||
* Reference to this NotificationAction.
|
||||
@@ -45,6 +48,13 @@ angular.module('notification').factory('NotificationAction', [function defineNot
|
||||
*/
|
||||
var action = this;
|
||||
|
||||
/**
|
||||
* The CSS class associated with this action.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.className = className;
|
||||
|
||||
/**
|
||||
* The name of this action.
|
||||
*
|
||||
|
@@ -30,12 +30,12 @@ angular.module('rest').factory('protocolService', ['$http', 'authenticationServi
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get the list of protocols, returning
|
||||
* a promise that provides an array of @link{Protocol} objects if
|
||||
* successful.
|
||||
* a promise that provides a map of @link{Protocol} objects by protocol
|
||||
* name if successful.
|
||||
*
|
||||
* @returns {Promise.<Protocol[]>}
|
||||
* A promise which will resolve with an array of @link{Protocol}
|
||||
* objects upon success.
|
||||
* @returns {Promise.<Object.<String, Protocol>>}
|
||||
* A promise which will resolve with a map of @link{Protocol}
|
||||
* objects by protocol name upon success.
|
||||
*/
|
||||
service.getProtocols = function getProtocols() {
|
||||
|
||||
|
155
guacamole/src/main/webapp/app/rest/types/PermissionFlagSet.js
Normal file
155
guacamole/src/main/webapp/app/rest/types/PermissionFlagSet.js
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A service for defining the PermissionFlagSet class.
|
||||
*/
|
||||
angular.module('rest').factory('PermissionFlagSet', ['PermissionSet',
|
||||
function definePermissionFlagSet(PermissionSet) {
|
||||
|
||||
/**
|
||||
* Alternative view of a @link{PermissionSet} which allows manipulation of
|
||||
* each permission through the setting (or retrieval) of boolean property
|
||||
* values.
|
||||
*
|
||||
* @constructor
|
||||
* @param {PermissionFlagSet|Object} template
|
||||
* The object whose properties should be copied within the new
|
||||
* PermissionFlagSet.
|
||||
*/
|
||||
var PermissionFlagSet = function PermissionFlagSet(template) {
|
||||
|
||||
// Use empty object by default
|
||||
template = template || {};
|
||||
|
||||
/**
|
||||
* The granted state of each system permission, as a map of system
|
||||
* permission type string 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.SystemPermissionType. Permissions which are not
|
||||
* granted may be set to false, but this is not required.
|
||||
*
|
||||
* @type Object.<String, Boolean>
|
||||
*/
|
||||
this.systemPermissions = template.systemPermissions || {};
|
||||
|
||||
/**
|
||||
* The granted state of each permission for each connection, as a map
|
||||
* of object permission type string to permission map. The permission
|
||||
* map is, in turn, a map of connection 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.connectionPermissions = template.connectionPermissions || {};
|
||||
|
||||
/**
|
||||
* The granted state of each permission for each connection group, as a
|
||||
* map of object permission type string to permission map. The
|
||||
* permission map is, in turn, a map of connection group 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.connectionGroupPermissions = template.connectionGroupPermissions || {};
|
||||
|
||||
/**
|
||||
* The granted state of each permission for each user, as a map of
|
||||
* object permission type string to permission map. The permission map
|
||||
* is, in turn, a map of username 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.userPermissions = template.userPermissions || {};
|
||||
|
||||
};
|
||||
|
||||
var addObjectPermissions = function addObjectPermissions(permMap, flagMap) {
|
||||
|
||||
// For each defined identifier in the permission map
|
||||
for (var identifier in permMap) {
|
||||
|
||||
// Pull the permission array and loop through each permission
|
||||
var permissions = permMap[identifier];
|
||||
permissions.forEach(function addObjectPermission(type) {
|
||||
|
||||
// Get identifier/flag mapping, creating first if necessary
|
||||
var objectFlags = flagMap[type] = flagMap[type] || {};
|
||||
|
||||
// Set flag for current permission
|
||||
objectFlags[identifier] = true;
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new PermissionFlagSet, populating it with all the permissions
|
||||
* indicated as granted within the given PermissionSet.
|
||||
*
|
||||
* @param {PermissionSet} permissionSet
|
||||
* The PermissionSet containing the permissions to be copied into a new
|
||||
* PermissionFlagSet.
|
||||
*
|
||||
* @returns {PermissionFlagSet}
|
||||
* A new PermissionFlagSet containing flags representing all granted
|
||||
* permissions from the given PermissionSet.
|
||||
*/
|
||||
PermissionFlagSet.fromPermissionSet = function fromPermissionSet(permissionSet) {
|
||||
|
||||
var permissionFlagSet = new PermissionFlagSet();
|
||||
|
||||
// Add all granted system permissions
|
||||
permissionSet.systemPermissions.forEach(function addSystemPermission(type) {
|
||||
permissionFlagSet.systemPermissions[type] = true;
|
||||
});
|
||||
|
||||
// Add all granted connection permissions
|
||||
addObjectPermissions(permissionSet.connectionPermissions, permissionFlagSet.connectionPermissions);
|
||||
|
||||
// Add all granted connection group permissions
|
||||
addObjectPermissions(permissionSet.connectionGroupPermissions, permissionFlagSet.connectionGroupPermissions);
|
||||
|
||||
// Add all granted user permissions
|
||||
addObjectPermissions(permissionSet.userPermissions, permissionFlagSet.userPermissions);
|
||||
|
||||
return permissionFlagSet;
|
||||
|
||||
};
|
||||
|
||||
return PermissionFlagSet;
|
||||
|
||||
}]);
|
@@ -275,6 +275,284 @@ angular.module('rest').factory('PermissionSet', [function definePermissionSet()
|
||||
return permSet.systemPermissions.indexOf(type) !== -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the given system permission 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.SystemPermissionType.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
* true if the permission was added, false if the permission was
|
||||
* already present in the given permission set.
|
||||
*/
|
||||
PermissionSet.addSystemPermission = function addSystemPermission(permSet, type) {
|
||||
|
||||
// Add permission, if it doesn't already exist
|
||||
if (permSet.systemPermissions.indexOf(type) === -1) {
|
||||
permSet.systemPermissions.push(type);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Permission already present
|
||||
return false;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the given system permission 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.SystemPermissionType.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
* true if the permission was removed, false if the permission was not
|
||||
* present in the given permission set.
|
||||
*/
|
||||
PermissionSet.removeSystemPermission = function removeSystemPermission(permSet, type) {
|
||||
|
||||
// Remove permission, if it exists
|
||||
var permLocation = permSet.systemPermissions.indexOf(type);
|
||||
if (permLocation !== -1) {
|
||||
permSet.systemPermissions.splice(permLocation, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Permission not present
|
||||
return false;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the given permission applying to the arbitrary object 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 {Object.<String, String[]>} permMap
|
||||
* The permission map to modify, where each entry maps an object
|
||||
* identifer to the array of granted permissions.
|
||||
*
|
||||
* @param {String} type
|
||||
* The permission to add, as defined by
|
||||
* PermissionSet.ObjectPermissionType.
|
||||
*
|
||||
* @param {String} identifier
|
||||
* The identifier of the arbitrary object 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.
|
||||
*/
|
||||
var addObjectPermission = function addObjectPermission(permMap, type, identifier) {
|
||||
|
||||
// Pull array of permissions, creating it if necessary
|
||||
var permArray = permMap[identifier] = permMap[identifier] || [];
|
||||
|
||||
// Add permission, if it doesn't already exist
|
||||
if (permArray.indexOf(type) === -1) {
|
||||
permArray.push(type);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Permission already present
|
||||
return false;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the given permission applying to the arbitrary object with the
|
||||
* given ID from the given permission set, if present. If the permission is
|
||||
* not present, this function has no effect.
|
||||
*
|
||||
* @param {Object.<String, String[]>} permMap
|
||||
* The permission map to modify, where each entry maps an object
|
||||
* identifer to the array of granted permissions.
|
||||
*
|
||||
* @param {String} type
|
||||
* The permission to remove, as defined by
|
||||
* PermissionSet.ObjectPermissionType.
|
||||
*
|
||||
* @param {String} identifier
|
||||
* The identifier of the arbitrary object 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.
|
||||
*/
|
||||
var removeObjectPermission = function removeObjectPermission(permMap, type, identifier) {
|
||||
|
||||
// Pull array of permissions
|
||||
var permArray = permMap[identifier];
|
||||
|
||||
// If no permissions present at all, nothing to remove
|
||||
if (!(identifier in permMap))
|
||||
return false;
|
||||
|
||||
// Remove permission, if it exists
|
||||
var permLocation = permArray.indexOf(type);
|
||||
if (permLocation !== -1) {
|
||||
permArray.splice(permLocation, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Permission not present
|
||||
return false;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the given connection permission applying to the connection 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 connection 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.addConnectionPermission = function addConnectionPermission(permSet, type, identifier) {
|
||||
return addObjectPermission(permSet.connectionPermissions, type, identifier);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the given connection permission applying to the connection 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 connection 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.removeConnectionPermission = function removeConnectionPermission(permSet, type, identifier) {
|
||||
return removeObjectPermission(permSet.connectionPermissions, type, identifier);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the given connection group permission applying to the connection
|
||||
* group 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 connection group 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.addConnectionGroupPermission = function addConnectionGroupPermission(permSet, type, identifier) {
|
||||
return addObjectPermission(permSet.connectionGroupPermissions, type, identifier);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the given connection group permission applying to the connection
|
||||
* group 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 connection group 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.removeConnectionGroupPermission = function removeConnectionGroupPermission(permSet, type, identifier) {
|
||||
return removeObjectPermission(permSet.connectionGroupPermissions, type, identifier);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the given user permission applying to the user 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 user 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.addUserPermission = function addUserPermission(permSet, type, identifier) {
|
||||
return addObjectPermission(permSet.userPermissions, type, identifier);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the given user permission applying to the user 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 user to whom the permission applies.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
* true if the permission was removed, false if the permission was not
|
||||
* present in the given permission set.
|
||||
*/
|
||||
PermissionSet.removeUserPermission = function removeUserPermission(permSet, type, identifier) {
|
||||
return removeObjectPermission(permSet.userPermissions, type, identifier);
|
||||
};
|
||||
|
||||
return PermissionSet;
|
||||
|
||||
}]);
|
@@ -39,16 +39,22 @@
|
||||
"newGroup" : "New Group",
|
||||
"edit": {
|
||||
"connection": {
|
||||
"title" : "Edit Connection",
|
||||
"cancel" : "Cancel",
|
||||
"save" : "Save",
|
||||
"delete" : "Delete",
|
||||
"confirmDelete" : {
|
||||
"title" : "Delete Connection",
|
||||
"text" : "Connections cannot be restored after they have been deleted. Are you sure you want to delete this connection?"
|
||||
},
|
||||
"protocol" : "Protocol:",
|
||||
"root" : "ROOT",
|
||||
"location" : "Location:",
|
||||
"name" : "Name:",
|
||||
"parameters" : "Parameters",
|
||||
"history" : {
|
||||
"connectionNotUsed" : "This connection has not yet been used.",
|
||||
"usageHistory" : "Usage History:",
|
||||
"usageHistory" : "Usage History",
|
||||
"username" : "Username",
|
||||
"startTime" : "Start Time",
|
||||
"duration" : "Duration",
|
||||
@@ -58,9 +64,14 @@
|
||||
}
|
||||
},
|
||||
"connectionGroup": {
|
||||
"title" : "Edit Connection Group",
|
||||
"cancel" : "Cancel",
|
||||
"save" : "Save",
|
||||
"delete" : "Delete",
|
||||
"confirmDelete" : {
|
||||
"title" : "Delete Connection",
|
||||
"text" : "Connection groups cannot be restored after they have been deleted. Are you sure you want to delete this connection group?"
|
||||
},
|
||||
"usageHistory" : "Usage History:",
|
||||
"type" : {
|
||||
"label" : "Type",
|
||||
@@ -72,18 +83,30 @@
|
||||
"name" : "Name:"
|
||||
},
|
||||
"user": {
|
||||
"title" : "Edit User",
|
||||
"cancel" : "Cancel",
|
||||
"save" : "Save",
|
||||
"delete" : "Delete",
|
||||
"properties" : "Properties:",
|
||||
"confirmDelete" : {
|
||||
"title" : "Delete User",
|
||||
"text" : "Users cannot be restored after they have been deleted. Are you sure you want to delete this user?"
|
||||
},
|
||||
"password" : "Password:",
|
||||
"passwordMatch" : "Re-enter Password:",
|
||||
"permissions" : "Permissions:",
|
||||
"passwordMismatch" : "The provided passwords do not match.",
|
||||
"permissions" : "Permissions",
|
||||
"username" : "Username:",
|
||||
"administerSystem" : "Administer system:",
|
||||
"createUser" : "Create new users:",
|
||||
"createConnection" : "Create new connections:",
|
||||
"createConnectionGroup" : "Create new connection groups:",
|
||||
"connections" : "Connections:"
|
||||
"connections" : "Connections"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"title" : "Error",
|
||||
"action": {
|
||||
"acknowledge" : "OK"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
Reference in New Issue
Block a user