GUACAMOLE-220: Map and query user group tables.

This commit is contained in:
Michael Jumper
2018-04-08 00:08:36 -07:00
parent 69f58c8ca3
commit c5c2984151
13 changed files with 1127 additions and 9 deletions

View File

@@ -65,6 +65,9 @@ import org.apache.guacamole.auth.jdbc.connection.ConnectionParameterMapper;
import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionMapper;
import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionService;
import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionSet;
import org.apache.guacamole.auth.jdbc.permission.UserGroupPermissionMapper;
import org.apache.guacamole.auth.jdbc.permission.UserGroupPermissionService;
import org.apache.guacamole.auth.jdbc.permission.UserGroupPermissionSet;
import org.apache.guacamole.auth.jdbc.security.PasswordPolicyService;
import org.apache.guacamole.auth.jdbc.sharing.ConnectionSharingService;
import org.apache.guacamole.auth.jdbc.sharing.HashSharedConnectionMap;
@@ -79,6 +82,10 @@ import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileService;
import org.apache.guacamole.auth.jdbc.tunnel.RestrictedGuacamoleTunnelService;
import org.apache.guacamole.auth.jdbc.user.PasswordRecordMapper;
import org.apache.guacamole.auth.jdbc.user.UserRecordMapper;
import org.apache.guacamole.auth.jdbc.usergroup.ModeledUserGroup;
import org.apache.guacamole.auth.jdbc.usergroup.UserGroupDirectory;
import org.apache.guacamole.auth.jdbc.usergroup.UserGroupMapper;
import org.apache.guacamole.auth.jdbc.usergroup.UserGroupService;
import org.mybatis.guice.MyBatisModule;
import org.mybatis.guice.datasource.builtin.PooledDataSourceProvider;
@@ -128,6 +135,8 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule {
addMapperClass(SharingProfileMapper.class);
addMapperClass(SharingProfileParameterMapper.class);
addMapperClass(SharingProfilePermissionMapper.class);
addMapperClass(UserGroupMapper.class);
addMapperClass(UserGroupPermissionMapper.class);
addMapperClass(UserMapper.class);
addMapperClass(UserPermissionMapper.class);
addMapperClass(UserRecordMapper.class);
@@ -146,12 +155,15 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule {
bind(ModeledSharingProfile.class);
bind(ModeledUser.class);
bind(ModeledUserContext.class);
bind(ModeledUserGroup.class);
bind(RootConnectionGroup.class);
bind(SharingProfileDirectory.class);
bind(SharingProfilePermissionSet.class);
bind(SystemPermissionSet.class);
bind(TrackedActiveConnection.class);
bind(UserDirectory.class);
bind(UserGroupDirectory.class);
bind(UserGroupPermissionSet.class);
bind(UserPermissionSet.class);
// Bind services
@@ -172,6 +184,8 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule {
bind(SharingProfilePermissionService.class);
bind(SharingProfileService.class);
bind(SystemPermissionService.class);
bind(UserGroupService.class);
bind(UserGroupPermissionService.class);
bind(UserPermissionService.class);
bind(UserService.class);

View File

@@ -28,13 +28,13 @@ import org.apache.guacamole.auth.jdbc.activeconnection.ActiveConnectionPermissio
import org.apache.guacamole.auth.jdbc.permission.ConnectionGroupPermissionService;
import org.apache.guacamole.auth.jdbc.permission.ConnectionPermissionService;
import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionService;
import org.apache.guacamole.auth.jdbc.permission.UserGroupPermissionService;
import org.apache.guacamole.auth.jdbc.permission.UserPermissionService;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
import org.apache.guacamole.net.auth.Permissions;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
import org.apache.guacamole.net.auth.permission.SystemPermission;
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
import org.apache.guacamole.net.auth.simple.SimpleObjectPermissionSet;
/**
* An implementation of the base Permissions interface which is common to both
@@ -88,6 +88,12 @@ public abstract class ModeledPermissions<ModelType extends EntityModel>
@Inject
private UserPermissionService userPermissionService;
/**
* Service for retrieving user group permissions.
*/
@Inject
private UserGroupPermissionService userGroupPermissionService;
/**
* Returns whether the underlying entity is a user. Entities may be either
* users or user groups.
@@ -171,8 +177,8 @@ public abstract class ModeledPermissions<ModelType extends EntityModel>
@Override
public ObjectPermissionSet getUserGroupPermissions() throws GuacamoleException {
// FIXME: STUB
return new SimpleObjectPermissionSet();
return userGroupPermissionService.getPermissionSet(getCurrentUser(),
this, Collections.<String>emptySet());
}
/**
@@ -256,8 +262,7 @@ public abstract class ModeledPermissions<ModelType extends EntityModel>
@Override
public ObjectPermissionSet getUserGroupPermissions()
throws GuacamoleException {
// FIXME: STUB
return new SimpleObjectPermissionSet();
return userGroupPermissionService.getPermissionSet(getCurrentUser(), ModeledPermissions.this, effectiveGroups);
}
};

View File

@@ -0,0 +1,25 @@
/*
* 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.auth.jdbc.permission;
/**
* Mapper for user group permissions.
*/
public interface UserGroupPermissionMapper extends ObjectPermissionMapper {}

View File

@@ -0,0 +1,67 @@
/*
* 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.auth.jdbc.permission;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.base.EntityModel;
import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
/**
* Service which provides convenience methods for creating, retrieving, and
* deleting user group permissions. This service will automatically enforce the
* permissions of the current user.
*/
public class UserGroupPermissionService extends ModeledObjectPermissionService {
/**
* Mapper for user group permissions.
*/
@Inject
private UserGroupPermissionMapper userGroupPermissionMapper;
/**
* Provider for user group permission sets.
*/
@Inject
private Provider<UserGroupPermissionSet> userGroupPermissionSetProvider;
@Override
protected ObjectPermissionMapper getPermissionMapper() {
return userGroupPermissionMapper;
}
@Override
public ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
ModeledPermissions<? extends EntityModel> targetEntity,
Set<String> effectiveGroups) throws GuacamoleException {
// Create permission set for requested entity
ObjectPermissionSet permissionSet = userGroupPermissionSetProvider.get();
permissionSet.init(user, targetEntity, effectiveGroups);
return permissionSet;
}
}

View File

@@ -0,0 +1,42 @@
/*
* 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.auth.jdbc.permission;
import com.google.inject.Inject;
/**
* A database implementation of ObjectPermissionSet which uses an injected
* service to query and manipulate the user group permissions associated with a
* particular user.
*/
public class UserGroupPermissionSet extends ObjectPermissionSet {
/**
* Service for querying and manipulating user group permissions.
*/
@Inject
private UserGroupPermissionService userGroupPermissionService;
@Override
protected ObjectPermissionService getObjectPermissionService() {
return userGroupPermissionService;
}
}

View File

@@ -26,7 +26,6 @@ import org.apache.guacamole.auth.jdbc.connection.ConnectionDirectory;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.base.RestrictedObject;
@@ -37,6 +36,8 @@ import org.apache.guacamole.auth.jdbc.connection.ModeledConnection;
import org.apache.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup;
import org.apache.guacamole.auth.jdbc.sharingprofile.ModeledSharingProfile;
import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileDirectory;
import org.apache.guacamole.auth.jdbc.usergroup.ModeledUserGroup;
import org.apache.guacamole.auth.jdbc.usergroup.UserGroupDirectory;
import org.apache.guacamole.form.Form;
import org.apache.guacamole.net.auth.ActiveConnection;
import org.apache.guacamole.net.auth.ActivityRecord;
@@ -48,7 +49,6 @@ import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.SharingProfile;
import org.apache.guacamole.net.auth.User;
import org.apache.guacamole.net.auth.UserGroup;
import org.apache.guacamole.net.auth.simple.SimpleDirectory;
/**
* UserContext implementation which is driven by an arbitrary, underlying
@@ -63,6 +63,13 @@ public class ModeledUserContext extends RestrictedObject
*/
@Inject
private UserDirectory userDirectory;
/**
* User group directory restricted by the permissions of the user associated
* with this context.
*/
@Inject
private UserGroupDirectory userGroupDirectory;
/**
* Connection directory restricted by the permissions of the user
@@ -128,6 +135,7 @@ public class ModeledUserContext extends RestrictedObject
// Init directories
userDirectory.init(currentUser);
userGroupDirectory.init(currentUser);
connectionDirectory.init(currentUser);
connectionGroupDirectory.init(currentUser);
sharingProfileDirectory.init(currentUser);
@@ -166,7 +174,7 @@ public class ModeledUserContext extends RestrictedObject
@Override
public Directory<UserGroup> getUserGroupDirectory() throws GuacamoleException {
return new SimpleDirectory<UserGroup>();
return userGroupDirectory;
}
@Override
@@ -224,7 +232,7 @@ public class ModeledUserContext extends RestrictedObject
@Override
public Collection<Form> getUserGroupAttributes() {
return Collections.<Form>emptyList();
return ModeledUserGroup.ATTRIBUTES;
}
@Override

View File

@@ -0,0 +1,191 @@
/*
* 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.auth.jdbc.usergroup;
import com.google.inject.Inject;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
import org.apache.guacamole.form.BooleanField;
import org.apache.guacamole.form.Field;
import org.apache.guacamole.form.Form;
import org.apache.guacamole.net.auth.RelatedObjectSet;
import org.apache.guacamole.net.auth.UserGroup;
import org.apache.guacamole.net.auth.simple.SimpleRelatedObjectSet;
/**
* An implementation of the UserGroup object which is backed by a database model.
*/
public class ModeledUserGroup extends ModeledPermissions<UserGroupModel>
implements UserGroup {
/**
* The name of the attribute which controls whether a user group is
* disabled.
*/
public static final String DISABLED_ATTRIBUTE_NAME = "disabled";
/**
* All attributes related to restricting user groups, within a logical
* form.
*/
public static final Form ACCOUNT_RESTRICTIONS = new Form("restrictions", Arrays.<Field>asList(
new BooleanField(DISABLED_ATTRIBUTE_NAME, "true")
));
/**
* All possible attributes of user groups organized as individual,
* logical forms.
*/
public static final Collection<Form> ATTRIBUTES = Collections.unmodifiableCollection(Arrays.asList(
ACCOUNT_RESTRICTIONS
));
/**
* The names of all attributes which are explicitly supported by this
* extension's UserGroup objects.
*/
public static final Set<String> ATTRIBUTE_NAMES =
Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
DISABLED_ATTRIBUTE_NAME
)));
/**
* Service for managing user groups.
*/
@Inject
private UserGroupService userGroupService;
/**
* Whether attributes which control access restrictions should be exposed
* via getAttributes() or allowed to be set via setAttributes().
*/
private boolean exposeRestrictedAttributes = false;
/**
* Initializes this ModeledUserGroup, associating it with the current
* authenticated user and populating it with data from the given user group
* model.
*
* @param currentUser
* The user that created or retrieved this object.
*
* @param model
* The backing model object.
*
* @param exposeRestrictedAttributes
* Whether attributes which control access restrictions should be
* exposed via getAttributes() or allowed to be set via
* setAttributes().
*/
public void init(ModeledAuthenticatedUser currentUser, UserGroupModel model,
boolean exposeRestrictedAttributes) {
super.init(currentUser, model);
this.exposeRestrictedAttributes = exposeRestrictedAttributes;
}
/**
* Creates a new, empty ModeledUserGroup.
*/
public ModeledUserGroup() {
}
/**
* Stores all restricted (privileged) attributes within the given Map,
* pulling the values of those attributes from the underlying user group
* model. If no value is yet defined for an attribute, that attribute will
* be set to null.
*
* @param attributes
* The Map to store all restricted attributes within.
*/
private void putRestrictedAttributes(Map<String, String> attributes) {
// Set disabled attribute
attributes.put(DISABLED_ATTRIBUTE_NAME, getModel().isDisabled() ? "true" : null);
}
/**
* Stores all restricted (privileged) attributes within the underlying user
* group model, pulling the values of those attributes from the given Map.
*
* @param attributes
* The Map to pull all restricted attributes from.
*/
private void setRestrictedAttributes(Map<String, String> attributes) {
// Translate disabled attribute
getModel().setDisabled("true".equals(attributes.get(DISABLED_ATTRIBUTE_NAME)));
}
@Override
public Set<String> getSupportedAttributeNames() {
return ATTRIBUTE_NAMES;
}
@Override
public Map<String, String> getAttributes() {
// Include any defined arbitrary attributes
Map<String, String> attributes = super.getAttributes();
// Include restricted attributes only if they should be exposed
if (exposeRestrictedAttributes)
putRestrictedAttributes(attributes);
return attributes;
}
@Override
public void setAttributes(Map<String, String> attributes) {
// Set arbitrary attributes
super.setAttributes(attributes);
// Assign restricted attributes only if they are exposed
if (exposeRestrictedAttributes)
setRestrictedAttributes(attributes);
}
@Override
public RelatedObjectSet getUserGroups() throws GuacamoleException {
return new SimpleRelatedObjectSet();
}
@Override
public RelatedObjectSet getMemberUsers() throws GuacamoleException {
return new SimpleRelatedObjectSet();
}
@Override
public RelatedObjectSet getMemberUserGroups() throws GuacamoleException {
return new SimpleRelatedObjectSet();
}
}

View File

@@ -0,0 +1,82 @@
/*
* 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.auth.jdbc.usergroup;
import com.google.inject.Inject;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.base.RestrictedObject;
import org.apache.guacamole.net.auth.Directory;
import org.apache.guacamole.net.auth.UserGroup;
import org.mybatis.guice.transactional.Transactional;
/**
* Implementation of the UserGroup Directory which is driven by an underlying,
* arbitrary database.
*/
public class UserGroupDirectory extends RestrictedObject
implements Directory<UserGroup> {
/**
* Service for managing user group objects.
*/
@Inject
private UserGroupService userGroupService;
@Override
public UserGroup get(String identifier) throws GuacamoleException {
return userGroupService.retrieveObject(getCurrentUser(), identifier);
}
@Override
@Transactional
public Collection<UserGroup> getAll(Collection<String> identifiers) throws GuacamoleException {
Collection<ModeledUserGroup> objects = userGroupService.retrieveObjects(getCurrentUser(), identifiers);
return Collections.<UserGroup>unmodifiableCollection(objects);
}
@Override
@Transactional
public Set<String> getIdentifiers() throws GuacamoleException {
return userGroupService.getIdentifiers(getCurrentUser());
}
@Override
@Transactional
public void add(UserGroup object) throws GuacamoleException {
userGroupService.createObject(getCurrentUser(), object);
}
@Override
@Transactional
public void update(UserGroup object) throws GuacamoleException {
ModeledUserGroup group = (ModeledUserGroup) object;
userGroupService.updateObject(getCurrentUser(), group);
}
@Override
@Transactional
public void remove(String identifier) throws GuacamoleException {
userGroupService.deleteObject(getCurrentUser(), identifier);
}
}

View File

@@ -0,0 +1,42 @@
/*
* 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.auth.jdbc.usergroup;
import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper;
import org.apache.ibatis.annotations.Param;
/**
* Mapper for user group objects.
*/
public interface UserGroupMapper extends ModeledDirectoryObjectMapper<UserGroupModel> {
/**
* Returns the group having the given name, if any. If no such group
* exists, null is returned.
*
* @param name
* The name of the group to return.
*
* @return
* The group having the given name, or null if no such group exists.
*/
UserGroupModel selectOne(@Param("name") String name);
}

View File

@@ -0,0 +1,68 @@
/*
* 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.auth.jdbc.usergroup;
import org.apache.guacamole.auth.jdbc.base.EntityModel;
import org.apache.guacamole.auth.jdbc.base.EntityType;
/**
* Object representation of a Guacamole user group, as represented in the
* database.
*/
public class UserGroupModel extends EntityModel {
/**
* Whether the user group is disabled. Disabled accounts exist and can
* be modified, but cannot be used.
*/
private boolean disabled;
/**
* Creates a new, empty user group.
*/
public UserGroupModel() {
super(EntityType.USER_GROUP);
}
/**
* Returns whether this user group has been disabled. Memberships of
* disabled user groups are treated as non-existent, effectively disabling
* membership in that group.
*
* @return
* true if this user group is disabled, false otherwise.
*/
public boolean isDisabled() {
return disabled;
}
/**
* Sets whether this user group has been disabled. Memberships of disabled
* user groups are treated as non-existent, effectively disabling
* membership in that group.
*
* @param disabled
* true if this user group should be disabled, false otherwise.
*/
public void setDisabled(boolean disabled) {
this.disabled = disabled;
}
}

View File

@@ -0,0 +1,189 @@
/*
* 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.auth.jdbc.usergroup;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Collection;
import java.util.Collections;
import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper;
import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectService;
import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.base.EntityMapper;
import org.apache.guacamole.auth.jdbc.permission.ObjectPermissionMapper;
import org.apache.guacamole.auth.jdbc.permission.UserGroupPermissionMapper;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
import org.apache.guacamole.net.auth.UserGroup;
import org.apache.guacamole.net.auth.permission.ObjectPermission;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
import org.apache.guacamole.net.auth.permission.SystemPermission;
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
/**
* Service which provides convenience methods for creating, retrieving, and
* manipulating user groups.
*/
public class UserGroupService extends ModeledDirectoryObjectService<ModeledUserGroup, UserGroup, UserGroupModel> {
/**
* Mapper for creating/deleting entities.
*/
@Inject
private EntityMapper entityMapper;
/**
* Mapper for accessing user groups.
*/
@Inject
private UserGroupMapper userGroupMapper;
/**
* Mapper for manipulating user group permissions.
*/
@Inject
private UserGroupPermissionMapper userGroupPermissionMapper;
/**
* Provider for creating user groups.
*/
@Inject
private Provider<ModeledUserGroup> userGroupProvider;
@Override
protected ModeledDirectoryObjectMapper<UserGroupModel> getObjectMapper() {
return userGroupMapper;
}
@Override
protected ObjectPermissionMapper getPermissionMapper() {
return userGroupPermissionMapper;
}
@Override
protected ModeledUserGroup getObjectInstance(ModeledAuthenticatedUser currentUser,
UserGroupModel model) throws GuacamoleException {
boolean exposeRestrictedAttributes;
// Expose restricted attributes if the user group does not yet exist
if (model.getObjectID() == null)
exposeRestrictedAttributes = true;
// Otherwise, expose restricted attributes only if the user has
// ADMINISTER permission
else
exposeRestrictedAttributes = hasObjectPermission(currentUser,
model.getIdentifier(), ObjectPermission.Type.ADMINISTER);
// Produce ModeledUserGroup exposing only those attributes for which the
// current user has permission
ModeledUserGroup group = userGroupProvider.get();
group.init(currentUser, model, exposeRestrictedAttributes);
return group;
}
@Override
protected UserGroupModel getModelInstance(ModeledAuthenticatedUser currentUser,
final UserGroup object) throws GuacamoleException {
// Create new ModeledUserGroup backed by blank model
UserGroupModel model = new UserGroupModel();
ModeledUserGroup group = getObjectInstance(currentUser, model);
// Set model contents through ModeledUser, copying the provided group
group.setIdentifier(object.getIdentifier());
group.setAttributes(object.getAttributes());
return model;
}
@Override
protected boolean hasCreatePermission(ModeledAuthenticatedUser user)
throws GuacamoleException {
// Return whether user has explicit user group creation permission
SystemPermissionSet permissionSet = user.getUser().getEffectivePermissions().getSystemPermissions();
return permissionSet.hasPermission(SystemPermission.Type.CREATE_USER);
}
@Override
protected ObjectPermissionSet getEffectivePermissionSet(ModeledAuthenticatedUser user)
throws GuacamoleException {
// Return permissions related to user groups
return user.getUser().getEffectivePermissions().getUserGroupPermissions();
}
@Override
protected void beforeCreate(ModeledAuthenticatedUser user, UserGroup object,
UserGroupModel model) throws GuacamoleException {
super.beforeCreate(user, object, model);
// Group name must not be blank
if (model.getIdentifier() == null || model.getIdentifier().trim().isEmpty())
throw new GuacamoleClientException("The group name must not be blank.");
// Do not create duplicate user groups
Collection<UserGroupModel> existing = userGroupMapper.select(Collections.singleton(model.getIdentifier()));
if (!existing.isEmpty())
throw new GuacamoleClientException("Group \"" + model.getIdentifier() + "\" already exists.");
// Create base entity object, implicitly populating underlying entity ID
entityMapper.insert(model);
}
@Override
protected void beforeUpdate(ModeledAuthenticatedUser user,
ModeledUserGroup object, UserGroupModel model) throws GuacamoleException {
super.beforeUpdate(user, object, model);
// Username must not be blank
if (model.getIdentifier() == null || model.getIdentifier().trim().isEmpty())
throw new GuacamoleClientException("The group name must not be blank.");
// Check whether such a group is already present
UserGroupModel existing = userGroupMapper.selectOne(model.getIdentifier());
if (existing != null) {
// Do not rename to existing user group
if (!existing.getObjectID().equals(model.getObjectID()))
throw new GuacamoleClientException("Group \"" + model.getIdentifier() + "\" already exists.");
}
}
@Override
protected boolean isValidIdentifier(String identifier) {
// All strings are valid group identifiers
return true;
}
}