1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20 package org.apache.guacamole.auth.jdbc.usergroup; 21 22 import com.google.inject.Inject; 23 import com.google.inject.Provider; 24 import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper; 25 import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectService; 26 import org.apache.guacamole.GuacamoleClientException; 27 import org.apache.guacamole.GuacamoleException; 28 import org.apache.guacamole.auth.jdbc.base.EntityMapper; 29 import org.apache.guacamole.auth.jdbc.permission.ObjectPermissionMapper; 30 import org.apache.guacamole.auth.jdbc.permission.UserGroupPermissionMapper; 31 import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser; 32 import org.apache.guacamole.net.auth.UserGroup; 33 import org.apache.guacamole.net.auth.permission.ObjectPermission; 34 import org.apache.guacamole.net.auth.permission.ObjectPermissionSet; 35 import org.apache.guacamole.net.auth.permission.SystemPermission; 36 import org.apache.guacamole.net.auth.permission.SystemPermissionSet; 37 38 /** 39 * Service which provides convenience methods for creating, retrieving, and 40 * manipulating user groups. 41 */ 42 public class UserGroupService extends ModeledDirectoryObjectService<ModeledUserGroup, UserGroup, UserGroupModel> { 43 44 /** 45 * Mapper for creating/deleting entities. 46 */ 47 @Inject 48 private EntityMapper entityMapper; 49 50 /** 51 * Mapper for accessing user groups. 52 */ 53 @Inject 54 private UserGroupMapper userGroupMapper; 55 56 /** 57 * Mapper for manipulating user group permissions. 58 */ 59 @Inject 60 private UserGroupPermissionMapper userGroupPermissionMapper; 61 62 /** 63 * Provider for creating user groups. 64 */ 65 @Inject 66 private Provider<ModeledUserGroup> userGroupProvider; 67 68 @Override getObjectMapper()69 protected ModeledDirectoryObjectMapper<UserGroupModel> getObjectMapper() { 70 return userGroupMapper; 71 } 72 73 @Override getPermissionMapper()74 protected ObjectPermissionMapper getPermissionMapper() { 75 return userGroupPermissionMapper; 76 } 77 78 @Override getObjectInstance(ModeledAuthenticatedUser currentUser, UserGroupModel model)79 protected ModeledUserGroup getObjectInstance(ModeledAuthenticatedUser currentUser, 80 UserGroupModel model) throws GuacamoleException { 81 82 boolean exposeRestrictedAttributes; 83 84 // Expose restricted attributes if the user group does not yet exist 85 if (model.getObjectID() == null) 86 exposeRestrictedAttributes = true; 87 88 // Otherwise, expose restricted attributes only if the user has 89 // ADMINISTER permission 90 else 91 exposeRestrictedAttributes = hasObjectPermission(currentUser, 92 model.getIdentifier(), ObjectPermission.Type.ADMINISTER); 93 94 // Produce ModeledUserGroup exposing only those attributes for which the 95 // current user has permission 96 ModeledUserGroup group = userGroupProvider.get(); 97 group.init(currentUser, model, exposeRestrictedAttributes); 98 return group; 99 100 } 101 102 @Override getModelInstance(ModeledAuthenticatedUser currentUser, final UserGroup object)103 protected UserGroupModel getModelInstance(ModeledAuthenticatedUser currentUser, 104 final UserGroup object) throws GuacamoleException { 105 106 // Create new ModeledUserGroup backed by blank model 107 UserGroupModel model = new UserGroupModel(); 108 ModeledUserGroup group = getObjectInstance(currentUser, model); 109 110 // Set model contents through ModeledUser, copying the provided group 111 group.setIdentifier(object.getIdentifier()); 112 group.setAttributes(object.getAttributes()); 113 114 return model; 115 116 } 117 118 @Override hasCreatePermission(ModeledAuthenticatedUser user)119 protected boolean hasCreatePermission(ModeledAuthenticatedUser user) 120 throws GuacamoleException { 121 122 // Return whether user has explicit user group creation permission 123 SystemPermissionSet permissionSet = user.getUser().getEffectivePermissions().getSystemPermissions(); 124 return permissionSet.hasPermission(SystemPermission.Type.CREATE_USER); 125 126 } 127 128 @Override getEffectivePermissionSet(ModeledAuthenticatedUser user)129 protected ObjectPermissionSet getEffectivePermissionSet(ModeledAuthenticatedUser user) 130 throws GuacamoleException { 131 132 // Return permissions related to user groups 133 return user.getUser().getEffectivePermissions().getUserGroupPermissions(); 134 135 } 136 137 @Override beforeCreate(ModeledAuthenticatedUser user, UserGroup object, UserGroupModel model)138 protected void beforeCreate(ModeledAuthenticatedUser user, UserGroup object, 139 UserGroupModel model) throws GuacamoleException { 140 141 super.beforeCreate(user, object, model); 142 143 // Group name must not be blank 144 if (model.getIdentifier() == null || model.getIdentifier().trim().isEmpty()) 145 throw new GuacamoleClientException("The group name must not be blank."); 146 147 // Do not create duplicate user groups 148 UserGroupModel existing = userGroupMapper.selectOne(model.getIdentifier()); 149 if (existing != null) 150 throw new GuacamoleClientException("Group \"" + model.getIdentifier() + "\" already exists."); 151 152 // Create base entity object, implicitly populating underlying entity ID 153 entityMapper.insert(model); 154 155 } 156 157 @Override beforeUpdate(ModeledAuthenticatedUser user, ModeledUserGroup object, UserGroupModel model)158 protected void beforeUpdate(ModeledAuthenticatedUser user, 159 ModeledUserGroup object, UserGroupModel model) throws GuacamoleException { 160 161 super.beforeUpdate(user, object, model); 162 163 // Group names must not be blank 164 if (model.getIdentifier() == null || model.getIdentifier().trim().isEmpty()) 165 throw new GuacamoleClientException("The group name must not be blank."); 166 167 // Do not allow groups to be renamed if the name collides with that of 168 // another, existing group 169 UserGroupModel existing = userGroupMapper.selectOne(model.getIdentifier()); 170 if (existing != null && !existing.getObjectID().equals(model.getObjectID())) 171 throw new GuacamoleClientException("Group \"" + model.getIdentifier() + "\" already exists."); 172 173 } 174 175 @Override isValidIdentifier(String identifier)176 protected boolean isValidIdentifier(String identifier) { 177 178 // All strings are valid group identifiers 179 return true; 180 181 } 182 183 } 184