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