GUACAMOLE-220: Add base API support for user groups. Refactor as minimally necessary.

This commit is contained in:
Michael Jumper
2018-04-19 14:17:25 -07:00
parent aac9d8795c
commit dfb07edf29
20 changed files with 720 additions and 71 deletions

View File

@@ -19,6 +19,9 @@
package org.apache.guacamole.net.auth;
import java.util.Collections;
import java.util.Set;
/**
* Basic implementation of an AuthenticatedUser which uses the username to
@@ -29,6 +32,11 @@ public abstract class AbstractAuthenticatedUser extends AbstractIdentifiable
// Prior functionality now resides within AbstractIdentifiable
@Override
public Set<String> getEffectiveUserGroups() {
return Collections.<String>emptySet();
}
@Override
public void invalidate() {
// Nothing to invalidate

View File

@@ -67,6 +67,19 @@ public abstract class AbstractUserContext implements UserContext {
return new SimpleDirectory<User>(self());
}
/**
* {@inheritDoc}
*
* <p>This implementation simply returns an empty {@link Directory}.
* Implementations that wish to expose user groups should override this
* function.
*/
@Override
public Directory<UserGroup> getUserGroupDirectory()
throws GuacamoleException {
return new SimpleDirectory<UserGroup>();
}
/**
* {@inheritDoc}
*
@@ -181,6 +194,18 @@ public abstract class AbstractUserContext implements UserContext {
return Collections.<Form>emptyList();
}
/**
* {@inheritDoc}
*
* <p>This implementation simply returns an empty {@link Collection}.
* Implementations that wish to expose custom user group attributes as
* fields within user group edit screens should override this function.
*/
@Override
public Collection<Form> getUserGroupAttributes() {
return Collections.<Form>emptyList();
}
/**
* {@inheritDoc}
*

View File

@@ -19,6 +19,7 @@
package org.apache.guacamole.net.auth;
import java.util.Set;
/**
* A user of the Guacamole web application who has been authenticated by an
@@ -49,6 +50,24 @@ public interface AuthenticatedUser extends Identifiable {
*/
Credentials getCredentials();
/**
* Returns a read-only set of the identifiers of all user groups which
* apply to this authenticated user. The exact semantics of what user
* groups apply are up to the implementation, and the user groups within
* this set may be implied, derived dynamically, inherited through multiple
* levels of group membership, etc.
*
* Note that, as with user identifiers, user group identifiers form the
* basis of identity which applies across authentication providers. It is
* expected that any two user groups having the same identifier represent
* the same group, even if defined by different authentication providers
*
* @return
* A read-only set of the identifiers of all user groups which apply
* to this authenticated user.
*/
Set<String> getEffectiveUserGroups();
/**
* Invalidates this authenticated user and their associated token such that
* they are no longer logged in. This function will be automatically

View File

@@ -124,4 +124,20 @@ public class DelegatingUser implements User {
return user.getUserPermissions();
}
@Override
public ObjectPermissionSet getUserGroupPermissions()
throws GuacamoleException {
return user.getUserGroupPermissions();
}
@Override
public RelatedObjectSet getUserGroups() throws GuacamoleException {
return user.getUserGroups();
}
@Override
public Permissions getEffectivePermissions() throws GuacamoleException {
return user.getEffectivePermissions();
}
}

View File

@@ -65,6 +65,11 @@ public class DelegatingUserContext implements UserContext {
return userContext.getUserDirectory();
}
@Override
public Directory<UserGroup> getUserGroupDirectory() throws GuacamoleException {
return userContext.getUserGroupDirectory();
}
@Override
public Directory<Connection> getConnectionDirectory()
throws GuacamoleException {
@@ -111,6 +116,11 @@ public class DelegatingUserContext implements UserContext {
return userContext.getUserAttributes();
}
@Override
public Collection<Form> getUserGroupAttributes() {
return userContext.getUserGroupAttributes();
}
@Override
public Collection<Form> getConnectionAttributes() {
return userContext.getConnectionAttributes();

View File

@@ -0,0 +1,125 @@
/*
* 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.net.auth;
import java.util.Map;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
/**
* UserGroup implementation which simply delegates all function calls to an
* underlying UserGroup.
*/
public class DelegatingUserGroup implements UserGroup {
/**
* The wrapped UserGroup.
*/
private final UserGroup userGroup;
/**
* Wraps the given UserGroup such that all function calls against this
* DelegatingUserGroup will be delegated to it.
*
* @param userGroup
* The UserGroup to wrap.
*/
public DelegatingUserGroup(UserGroup userGroup) {
this.userGroup = userGroup;
}
@Override
public String getIdentifier() {
return userGroup.getIdentifier();
}
@Override
public void setIdentifier(String identifier) {
userGroup.setIdentifier(identifier);
}
@Override
public Map<String, String> getAttributes() {
return userGroup.getAttributes();
}
@Override
public void setAttributes(Map<String, String> attributes) {
userGroup.setAttributes(attributes);
}
@Override
public SystemPermissionSet getSystemPermissions()
throws GuacamoleException {
return userGroup.getSystemPermissions();
}
@Override
public ObjectPermissionSet getConnectionPermissions()
throws GuacamoleException {
return userGroup.getConnectionPermissions();
}
@Override
public ObjectPermissionSet getConnectionGroupPermissions()
throws GuacamoleException {
return userGroup.getConnectionGroupPermissions();
}
@Override
public ObjectPermissionSet getSharingProfilePermissions()
throws GuacamoleException {
return userGroup.getSharingProfilePermissions();
}
@Override
public ObjectPermissionSet getActiveConnectionPermissions()
throws GuacamoleException {
return userGroup.getActiveConnectionPermissions();
}
@Override
public ObjectPermissionSet getUserPermissions() throws GuacamoleException {
return userGroup.getUserPermissions();
}
@Override
public ObjectPermissionSet getUserGroupPermissions()
throws GuacamoleException {
return userGroup.getUserGroupPermissions();
}
@Override
public RelatedObjectSet getUserGroups() throws GuacamoleException {
return userGroup.getUserGroups();
}
@Override
public RelatedObjectSet getMemberUsers() throws GuacamoleException {
return userGroup.getMemberUsers();
}
@Override
public RelatedObjectSet getMemberUserGroups() throws GuacamoleException {
return userGroup.getMemberUserGroups();
}
}

View File

@@ -0,0 +1,129 @@
/*
* 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.net.auth;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
/**
* An object which may be granted permissions to access/manipulate various
* other objects or aspects of the system. The permissions granted are exposed
* through subclasses of PermissionSet, and may be mutable depending on the
* access level of the current user.
*/
public interface Permissions {
/**
* Returns all permissions given to this object regarding currently-active
* connections.
*
* @return
* An ObjectPermissionSet of all active connection permissions granted
* to this object.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions, or if reading all
* permissions is not allowed.
*/
ObjectPermissionSet getActiveConnectionPermissions()
throws GuacamoleException;
/**
* Returns all connection group permissions given to this object.
*
* @return
* An ObjectPermissionSet of all connection group permissions granted
* to this object.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions, or if reading all
* permissions is not allowed.
*/
ObjectPermissionSet getConnectionGroupPermissions()
throws GuacamoleException;
/**
* Returns all connection permissions given to this object.
*
* @return
* An ObjectPermissionSet of all connection permissions granted to this
* object.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions, or if reading all
* permissions is not allowed.
*/
ObjectPermissionSet getConnectionPermissions() throws GuacamoleException;
/**
* Returns all sharing profile permissions given to this object.
*
* @return
* An ObjectPermissionSet of all sharing profile permissions granted to
* this object.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions, or if reading all
* permissions is not allowed.
*/
ObjectPermissionSet getSharingProfilePermissions()
throws GuacamoleException;
/**
* Returns all system-level permissions given to this object.
*
* @return
* A SystemPermissionSet of all system-level permissions granted to
* this object.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions, or if reading all
* permissions is not allowed.
*/
SystemPermissionSet getSystemPermissions() throws GuacamoleException;
/**
* Returns all user permissions given to this object.
*
* @return
* An ObjectPermissionSet of all user permissions granted to this
* object.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions, or if reading all
* permissions is not allowed.
*/
ObjectPermissionSet getUserPermissions() throws GuacamoleException;
/**
* Returns all user group permissions given to this object.
*
* @return
* An ObjectPermissionSet of all user group permissions granted to this
* object.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions, or if reading all
* permissions is not allowed.
*/
ObjectPermissionSet getUserGroupPermissions() throws GuacamoleException;
}

View File

@@ -0,0 +1,78 @@
/*
* 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.net.auth;
import java.util.Set;
import org.apache.guacamole.GuacamoleException;
/**
* An arbitrary set of existing objects sharing some common relation. Unlike a
* Directory, which provides for maintaining the entire lifecycle of its
* objects, a RelatedObjectSet only maintains the relation between its
* containing object and the objects within the set. Adding/removing an object
* from a RelatedObjectSet affects only the status of the specific relationship
* represented by the RelatedObjectSet, not the existence of the objects
* themselves.
*/
public interface RelatedObjectSet {
/**
* Returns a Set which contains the identifiers of all objects contained
* within this RelatedObjectSet.
*
* @return
* A Set which contains the identifiers of all objects contained
* within this RelatedObjectSet.
*
* @throws GuacamoleException
* If an error occurs while retrieving the objects within the set, or
* if objects cannot be retrieved due to lack of permissions to do so.
*/
Set<String> getObjects() throws GuacamoleException;
/**
* Adds the objects having the given identifiers, if not already present.
* If a specified object is already present, no operation is performed
* regarding that object.
*
* @param identifiers
* The identifiers of all objects being added.
*
* @throws GuacamoleException
* If an error occurs while adding the objects, or if permission to add
* objects is denied.
*/
void addObjects(Set<String> identifiers) throws GuacamoleException;
/**
* Removes each of the objects having the specified identifiers, if
* present. If a specified object is not present, no operation is performed
* regarding that object.
*
* @param identifiers
* The identifiers of all objects being removed.
*
* @throws GuacamoleException
* If an error occurs while removing the objects, or if permission to
* remove objects is denied.
*/
void removeObjects(Set<String> identifiers) throws GuacamoleException;
}

View File

@@ -22,14 +22,11 @@ package org.apache.guacamole.net.auth;
import java.util.Date;
import java.util.List;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
/**
* A user of the Guacamole web application.
*/
public interface User extends Identifiable, Attributes {
public interface User extends Identifiable, Attributes, Permissions {
/**
* All standard attribute names with semantics defined by the Guacamole web
@@ -109,85 +106,33 @@ public interface User extends Identifiable, Attributes {
List<? extends ActivityRecord> getHistory() throws GuacamoleException;
/**
* Returns all system-level permissions given to this user.
* Returns a set of all readable user groups of which this user is a member.
* If permission is granted for the current user to modify the membership of
* this user, then the returned set will be mutable, and any such
* modifications should be made through changes to the returned set.
*
* @return
* A SystemPermissionSet of all system-level permissions granted to
* this user.
* The set of all readable user groups of which this user is a member.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions, or if reading all
* permissions is not allowed.
* @throws GuacamoleException
* If an error occurs while retrieving the user groups.
*/
SystemPermissionSet getSystemPermissions() throws GuacamoleException;
RelatedObjectSet getUserGroups() throws GuacamoleException;
/**
* Returns all connection permissions given to this user.
* Returns a read-only view of all permissions granted to this user. The
* exact semantics of what permissions are granted are up to the
* implementation, and the permissions within this view may implied,
* derived dynamically, inherited through multiple levels of group
* membership, etc.
*
* @return
* An ObjectPermissionSet of all connection permissions granted to this
* user.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions, or if reading all
* permissions is not allowed.
*/
ObjectPermissionSet getConnectionPermissions()
throws GuacamoleException;
/**
* Returns all connection group permissions given to this user.
*
* @return
* An ObjectPermissionSet of all connection group permissions granted
* to this user.
* A read-only view of the permissions which are granted to this user.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions, or if reading all
* permissions is not allowed.
*/
ObjectPermissionSet getConnectionGroupPermissions()
throws GuacamoleException;
/**
* Returns all sharing profile permissions given to this user.
*
* @return
* An ObjectPermissionSet of all sharing profile permissions granted to
* this user.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions, or if reading all
* permissions is not allowed.
*/
ObjectPermissionSet getSharingProfilePermissions()
throws GuacamoleException;
/**
* Returns all permissions given to this user regarding currently-active
* connections.
*
* @return
* An ObjectPermissionSet of all active connection permissions granted
* to this user.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions, or if reading all
* permissions is not allowed.
*/
ObjectPermissionSet getActiveConnectionPermissions()
throws GuacamoleException;
/**
* Returns all user permissions given to this user.
*
* @return
* An ObjectPermissionSet of all user permissions granted to this user.
*
* @throws GuacamoleException
* If an error occurs while retrieving permissions, or if reading all
* permissions is not allowed.
*/
ObjectPermissionSet getUserPermissions() throws GuacamoleException;
Permissions getEffectivePermissions() throws GuacamoleException;
}

View File

@@ -84,6 +84,20 @@ public interface UserContext {
*/
Directory<User> getUserDirectory() throws GuacamoleException;
/**
* Retrieves a Directory which can be used to view and manipulate user
* groups, but only as allowed by the permissions given to the user of this
* UserContext.
*
* @return
* A Directory whose operations are bound by the restrictions
* of this UserContext.
*
* @throws GuacamoleException
* If an error occurs while creating the Directory.
*/
Directory<UserGroup> getUserGroupDirectory() throws GuacamoleException;
/**
* Retrieves a Directory which can be used to view and manipulate
* connections and their configurations, but only as allowed by the
@@ -197,6 +211,17 @@ public interface UserContext {
*/
Collection<Form> getUserAttributes();
/**
* Retrieves a collection of all attributes applicable to user groups. This
* collection will contain only those attributes which the current user has
* general permission to view or modify. If there are no such attributes,
* this collection will be empty.
*
* @return
* A collection of all attributes applicable to user groups.
*/
Collection<Form> getUserGroupAttributes();
/**
* Retrieves a collection of all attributes applicable to connections. This
* collection will contain only those attributes which the current user has

View File

@@ -0,0 +1,76 @@
/*
* 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.net.auth;
import org.apache.guacamole.GuacamoleException;
/**
* A user group of the Guacamole web application. Each user group may contain
* any number of Guacamole users and other user groups, and defines the
* permissions implicitly granted to its members.
*/
public interface UserGroup extends Identifiable, Attributes, Permissions {
/**
* Returns a set of all readable user groups that are members of this user
* group. If permission is granted for the current user to modify the
* members of this group, then the returned set will be mutable, and any
* such modifications should be made through changes to the returned set.
*
* @return
* The set of all readable user groups that are members of this user
* group, which may be mutable.
*
* @throws GuacamoleException
* If an error occurs while retrieving the user groups.
*/
RelatedObjectSet getUserGroups() throws GuacamoleException;
/**
* Returns a set of all readable users that are members of this user group.
* If permission is granted for the current user to modify the members of
* this group, then the returned set will be mutable, and any such
* modifications should be made through changes to the returned set.
*
* @return
* The set all readable users that are members of this user group,
* which may be mutable.
*
* @throws GuacamoleException
* If an error occurs while retrieving the users.
*/
RelatedObjectSet getMemberUsers() throws GuacamoleException;
/**
* Returns a set of all readable user groups that are members of this user
* group. If permission is granted for the current user to modify the
* members of this group, then the returned set will be mutable, and any
* such modifications should be made through changes to the returned set.
*
* @return
* The set of all readable user groups that are members of this user
* group, which may be mutable.
*
* @throws GuacamoleException
* If an error occurs while retrieving the user groups.
*/
RelatedObjectSet getMemberUserGroups() throws GuacamoleException;
}

View File

@@ -19,7 +19,9 @@
package org.apache.guacamole.net.auth.simple;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.AbstractAuthenticatedUser;
@@ -131,6 +133,11 @@ public abstract class SimpleAuthenticationProvider
return credentials;
}
@Override
public Set<String> getEffectiveUserGroups() {
return Collections.<String>emptySet();
}
}
/**

View File

@@ -0,0 +1,88 @@
/*
* 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.net.auth.simple;
import java.util.Collections;
import java.util.Set;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleSecurityException;
import org.apache.guacamole.net.auth.RelatedObjectSet;
/**
* A read-only implementation of RelatedObjectSet which uses a backing Set
* of identifiers to determine which objects are present.
*/
public class SimpleRelatedObjectSet implements RelatedObjectSet {
/**
* A set containing the identifiers of all objects currently present.
*/
private Set<String> identifiers = Collections.<String>emptySet();
/**
* Creates a new empty SimpleObjectPermissionSet.
*/
public SimpleRelatedObjectSet() {
}
/**
* Creates a new SimpleRelatedObjectSet which contains the objects having
* the identifiers within the given Set. The given Set backs the contents
* of the new SimpleRelatedObjectSet. While the SimpleRelatedObjectSet is
* read-only, any changes to the underlying Set will be reflected in the
* SimpleRelatedObjectSet.
*
* @param identifiers
* The Set containing the identifiers of all objects which should be
* present within the new SimpleRelatedObjectSet.
*/
public SimpleRelatedObjectSet(Set<String> identifiers) {
this.identifiers = identifiers;
}
/**
* Replaces the Set of object identifiers which backs this
* SimpleRelatedObjectSet. Future function calls on this
* SimpleRelatedObjectSet will instead use the provided Set.
*
* @param identifiers
* The Set containing the identifiers of all objects which should be
* present within this SimpleRelatedObjectSet.
*/
protected void setObjects(Set<String> identifiers) {
this.identifiers = identifiers;
}
@Override
public Set<String> getObjects() {
return identifiers;
}
@Override
public void addObjects(Set<String> identifiers) throws GuacamoleException {
throw new GuacamoleSecurityException("Permission denied.");
}
@Override
public void removeObjects(Set<String> identifiers) throws GuacamoleException {
throw new GuacamoleSecurityException("Permission denied.");
}
}

View File

@@ -29,6 +29,8 @@ import java.util.Set;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.AbstractUser;
import org.apache.guacamole.net.auth.ActivityRecord;
import org.apache.guacamole.net.auth.Permissions;
import org.apache.guacamole.net.auth.RelatedObjectSet;
import org.apache.guacamole.net.auth.permission.ObjectPermission;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
@@ -200,6 +202,12 @@ public class SimpleUser extends AbstractUser {
return new SimpleObjectPermissionSet(userPermissions);
}
@Override
public ObjectPermissionSet getUserGroupPermissions()
throws GuacamoleException {
return new SimpleObjectPermissionSet();
}
@Override
public ObjectPermissionSet getActiveConnectionPermissions()
throws GuacamoleException {
@@ -211,4 +219,14 @@ public class SimpleUser extends AbstractUser {
return new SimpleObjectPermissionSet();
}
@Override
public RelatedObjectSet getUserGroups() throws GuacamoleException {
return new SimpleRelatedObjectSet();
}
@Override
public Permissions getEffectivePermissions() throws GuacamoleException {
return this;
}
}