blob: 739a39c5e01f99a764748aaaa56d296a2c6262e6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.rest.permission;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.Permissions;
import org.apache.guacamole.net.auth.permission.ObjectPermission;
import org.apache.guacamole.net.auth.permission.Permission;
import org.apache.guacamole.net.auth.permission.SystemPermission;
import org.apache.guacamole.rest.APIPatch;
import org.apache.guacamole.rest.PATCH;
/**
* A REST resource which abstracts the operations available on the permissions
* granted to an existing User or UserGroup.
*/
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class PermissionSetResource {
/**
* The prefix of any path within an operation of a JSON patch which modifies
* the permissions of a user or user group regarding a specific connection.
*/
private static final String CONNECTION_PERMISSION_PATCH_PATH_PREFIX = "/connectionPermissions/";
/**
* The prefix of any path within an operation of a JSON patch which modifies
* the permissions of a user or user group regarding a specific connection
* group.
*/
private static final String CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX = "/connectionGroupPermissions/";
/**
* The prefix of any path within an operation of a JSON patch which modifies
* the permissions of a user or user group regarding a specific sharing
* profile.
*/
private static final String SHARING_PROFILE_PERMISSION_PATCH_PATH_PREFIX = "/sharingProfilePermissions/";
/**
* The prefix of any path within an operation of a JSON patch which modifies
* the permissions of a user or user group regarding a specific active
* connection.
*/
private static final String ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX = "/activeConnectionPermissions/";
/**
* The prefix of any path within an operation of a JSON patch which modifies
* the permissions of a user or user group regarding a specific user.
*/
private static final String USER_PERMISSION_PATCH_PATH_PREFIX = "/userPermissions/";
/**
* The prefix of any path within an operation of a JSON patch which modifies
* the permissions of a user or user group regarding a specific user group.
*/
private static final String USER_GROUP_PERMISSION_PATCH_PATH_PREFIX = "/userGroupPermissions/";
/**
* The path of any operation within a JSON patch which modifies the
* permissions of a user or user group regarding the entire system.
*/
private static final String SYSTEM_PERMISSION_PATCH_PATH = "/systemPermissions";
/**
* The permissions represented by this PermissionSetResource.
*/
private final Permissions permissions;
/**
* Creates a new PermissionSetResource which exposes the operations and
* subresources available for the given Permissions object.
*
* @param permissions
* The permissions that should be represented by this
* PermissionSetResource.
*/
public PermissionSetResource(Permissions permissions) {
this.permissions = permissions;
}
/**
* Gets a list of all permissions granted to the user or user group
* associated with this PermissionSetResource.
*
* @return
* A list of all permissions granted to the user or user group
* associated with this PermissionSetResource.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions.
*/
@GET
public APIPermissionSet getPermissions() throws GuacamoleException {
return new APIPermissionSet(permissions);
}
/**
* Updates the given permission set patch by queuing an add or remove
* operation for the given permission based on the given patch operation.
*
* @param <PermissionType>
* The type of permission stored within the permission set.
*
* @param operation
* The patch operation to perform.
*
* @param permissionSetPatch
* The permission set patch being modified.
*
* @param permission
* The permission being added or removed from the set.
*
* @throws GuacamoleException
* If the requested patch operation is not supported.
*/
private <PermissionType extends Permission> void updatePermissionSet(
APIPatch.Operation operation,
PermissionSetPatch<PermissionType> permissionSetPatch,
PermissionType permission) throws GuacamoleException {
// Add or remove permission based on operation
switch (operation) {
// Add permission
case add:
permissionSetPatch.addPermission(permission);
break;
// Remove permission
case remove:
permissionSetPatch.removePermission(permission);
break;
// Unsupported patch operation
default:
throw new GuacamoleClientException("Unsupported patch operation: \"" + operation + "\"");
}
}
/**
* Applies a given list of permission patches. Each patch specifies either
* an "add" or a "remove" operation for a permission type, represented by
* a string. Valid permission types depend on the path of each patch
* operation, as the path dictates the permission being modified, such as
* "/connectionPermissions/42" or "/systemPermissions".
*
* @param patches
* The permission patches to apply for this request.
*
* @throws GuacamoleException
* If a problem is encountered while modifying permissions.
*/
@PATCH
public void patchPermissions(List<APIPatch<String>> patches)
throws GuacamoleException {
// Permission patches for all types of permissions
PermissionSetPatch<ObjectPermission> connectionPermissionPatch = new PermissionSetPatch<ObjectPermission>();
PermissionSetPatch<ObjectPermission> connectionGroupPermissionPatch = new PermissionSetPatch<ObjectPermission>();
PermissionSetPatch<ObjectPermission> sharingProfilePermissionPatch = new PermissionSetPatch<ObjectPermission>();
PermissionSetPatch<ObjectPermission> activeConnectionPermissionPatch = new PermissionSetPatch<ObjectPermission>();
PermissionSetPatch<ObjectPermission> userPermissionPatch = new PermissionSetPatch<ObjectPermission>();
PermissionSetPatch<ObjectPermission> userGroupPermissionPatch = new PermissionSetPatch<ObjectPermission>();
PermissionSetPatch<SystemPermission> systemPermissionPatch = new PermissionSetPatch<SystemPermission>();
// Apply all patch operations individually
for (APIPatch<String> patch : patches) {
String path = patch.getPath();
// Create connection permission if path has connection prefix
if (path.startsWith(CONNECTION_PERMISSION_PATCH_PATH_PREFIX)) {
// Get identifier and type from patch operation
String identifier = path.substring(CONNECTION_PERMISSION_PATCH_PATH_PREFIX.length());
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
// Create and update corresponding permission
ObjectPermission permission = new ObjectPermission(type, identifier);
updatePermissionSet(patch.getOp(), connectionPermissionPatch, permission);
}
// Create connection group permission if path has connection group prefix
else if (path.startsWith(CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX)) {
// Get identifier and type from patch operation
String identifier = path.substring(CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX.length());
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
// Create and update corresponding permission
ObjectPermission permission = new ObjectPermission(type, identifier);
updatePermissionSet(patch.getOp(), connectionGroupPermissionPatch, permission);
}
// Create sharing profile permission if path has sharing profile prefix
else if (path.startsWith(SHARING_PROFILE_PERMISSION_PATCH_PATH_PREFIX)) {
// Get identifier and type from patch operation
String identifier = path.substring(SHARING_PROFILE_PERMISSION_PATCH_PATH_PREFIX.length());
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
// Create and update corresponding permission
ObjectPermission permission = new ObjectPermission(type, identifier);
updatePermissionSet(patch.getOp(), sharingProfilePermissionPatch, permission);
}
// Create active connection permission if path has active connection prefix
else if (path.startsWith(ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX)) {
// Get identifier and type from patch operation
String identifier = path.substring(ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX.length());
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
// Create and update corresponding permission
ObjectPermission permission = new ObjectPermission(type, identifier);
updatePermissionSet(patch.getOp(), activeConnectionPermissionPatch, permission);
}
// Create user permission if path has user prefix
else if (path.startsWith(USER_PERMISSION_PATCH_PATH_PREFIX)) {
// Get identifier and type from patch operation
String identifier = path.substring(USER_PERMISSION_PATCH_PATH_PREFIX.length());
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
// Create and update corresponding permission
ObjectPermission permission = new ObjectPermission(type, identifier);
updatePermissionSet(patch.getOp(), userPermissionPatch, permission);
}
// Create user group permission if path has user group prefix
else if (path.startsWith(USER_GROUP_PERMISSION_PATCH_PATH_PREFIX)) {
// Get identifier and type from patch operation
String identifier = path.substring(USER_GROUP_PERMISSION_PATCH_PATH_PREFIX.length());
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
// Create and update corresponding permission
ObjectPermission permission = new ObjectPermission(type, identifier);
updatePermissionSet(patch.getOp(), userGroupPermissionPatch, permission);
}
// Create system permission if path is system path
else if (path.equals(SYSTEM_PERMISSION_PATCH_PATH)) {
// Get identifier and type from patch operation
SystemPermission.Type type = SystemPermission.Type.valueOf(patch.getValue());
// Create and update corresponding permission
SystemPermission permission = new SystemPermission(type);
updatePermissionSet(patch.getOp(), systemPermissionPatch, permission);
}
// Otherwise, the path is not supported
else
throw new GuacamoleClientException("Unsupported patch path: \"" + path + "\"");
} // end for each patch operation
// Save the permission changes
connectionPermissionPatch.apply(permissions.getConnectionPermissions());
connectionGroupPermissionPatch.apply(permissions.getConnectionGroupPermissions());
sharingProfilePermissionPatch.apply(permissions.getSharingProfilePermissions());
activeConnectionPermissionPatch.apply(permissions.getActiveConnectionPermissions());
userPermissionPatch.apply(permissions.getUserPermissions());
userGroupPermissionPatch.apply(permissions.getUserGroupPermissions());
systemPermissionPatch.apply(permissions.getSystemPermissions());
}
}