]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
8e436a4fd6eeac79a88f0b5625db43c308302434
[tmp/jakarta-migration.git] /
1 /**
2  *  This document is a part of the source code and related artifacts
3  *  for CollectionSpace, an open source collections management system
4  *  for museums and related institutions:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS,
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  */
24 package org.collectionspace.services.authorization.storage;
25
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.UUID;
29
30 import org.collectionspace.services.authorization.PermissionRole;
31 import org.collectionspace.services.authorization.PermissionRoleSubResource;
32 import org.collectionspace.services.authorization.PermissionValue;
33 import org.collectionspace.services.authorization.Role;
34 import org.collectionspace.services.authorization.RoleValue;
35 import org.collectionspace.services.authorization.RolesList;
36 import org.collectionspace.services.authorization.SubjectType;
37
38 import org.collectionspace.services.client.PermissionRoleFactory;
39 import org.collectionspace.services.client.RoleClient;
40 import org.collectionspace.services.client.RoleFactory;
41 import org.collectionspace.services.common.api.Tools;
42 import org.collectionspace.services.common.context.ServiceContext;
43 import org.collectionspace.services.common.document.BadRequestException;
44 import org.collectionspace.services.common.document.DocumentFilter;
45 import org.collectionspace.services.common.document.DocumentWrapper;
46 import org.collectionspace.services.common.document.JaxbUtils;
47 import org.collectionspace.services.common.security.SecurityUtils;
48 import org.collectionspace.services.common.storage.TransactionContext;
49 import org.collectionspace.services.common.storage.jpa.JpaDocumentHandler;
50
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 /**
55  * Document handler for Role
56  * @author 
57  */
58 @SuppressWarnings("unchecked")
59 public class RoleDocumentHandler
60                 extends JpaDocumentHandler<Role, RolesList, Role, List<Role>> {
61     private final Logger logger = LoggerFactory.getLogger(RoleDocumentHandler.class);
62     private Role role;
63     private RolesList rolesList;
64
65     @Override
66     public void handleCreate(DocumentWrapper<Role> wrapDoc) throws Exception {
67         String id = UUID.randomUUID().toString();
68         Role role = wrapDoc.getWrappedObject();
69         
70         // Synthesize the display name if it was not passed in.
71         String displayName = role.getDisplayName();
72         boolean displayNameEmpty = true;
73         if (displayName != null) {
74                 displayNameEmpty = displayName.trim().isEmpty();        
75         }
76         if (displayNameEmpty == true) {
77                 role.setDisplayName(role.getRoleName());
78         }
79         
80         setTenant(role);
81         role.setRoleName(RoleClient.getBackendRoleName(role.getRoleName(), role.getTenantId()));
82         role.setCsid(id);
83         // We do not allow creation of locked roles through the services.
84         role.setMetadataProtection(null);
85         role.setPermsProtection(null);        
86     }
87     
88     @SuppressWarnings("rawtypes")
89         @Override
90         public void handleUpdate(DocumentWrapper<Role> wrapDoc) throws Exception {
91                 Role roleFound = wrapDoc.getWrappedObject();
92                 Role roleReceived = getCommonPart();
93                 // If marked as metadata immutable, do not do update
94                 if (!RoleClient.IMMUTABLE.equals(roleFound.getMetadataProtection())) {
95                         roleReceived
96                                         .setRoleName(RoleClient.getBackendRoleName(roleReceived.getRoleName(), roleFound.getTenantId()));
97                         merge(roleReceived, roleFound);
98                 }
99                 //
100                 // Update perms is supplied.
101                 //
102                 ServiceContext ctx = this.getServiceContext();
103                 List<PermissionValue> permValueList = roleReceived.getPermission();
104                 if (permValueList != null && permValueList.size() > 0) {
105             PermissionRoleSubResource subResource =
106                     new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
107             //
108             // First, delete the existing permroles
109             //
110             subResource.deletePermissionRole(ctx, roleFound.getCsid(), SubjectType.PERMISSION);
111             //
112             // Next, create the new permroles
113             //
114                 RoleValue roleValue = RoleFactory.createRoleValueInstance(roleFound);
115                 PermissionRole permRole = PermissionRoleFactory.createPermissionRoleInstance(SubjectType.PERMISSION, roleValue,
116                                 permValueList, true, true);            
117             subResource.createPermissionRole(ctx, permRole, SubjectType.PERMISSION);
118             //
119             // Finally, set the updated perm list in the result
120             //
121             PermissionRole newPermRole = subResource.getPermissionRole(ctx, roleFound.getCsid(), SubjectType.PERMISSION);
122             roleFound.setPermission(newPermRole.getPermission());
123                 }
124         }
125
126     /**
127      * Merge fields manually from 'from' to the 'to' role
128      * -this method is created due to inefficiency of JPA EM merge
129      * @param from
130      * @param to
131      * @return merged role
132      */
133     private Role merge(Role from, Role to) throws Exception {
134         // A role's name cannot be changed
135         if (!(from.getRoleName().equalsIgnoreCase(to.getRoleName()))) {
136             String msg = "Role name cannot be changed " + to.getRoleName();
137             logger.error(msg);
138             throw new BadRequestException(msg);
139         }
140         
141         if (from.getDisplayName() != null && !from.getDisplayName().trim().isEmpty() ) {
142                 to.setDisplayName(from.getDisplayName());
143         }
144         if (from.getRoleGroup() != null && !from.getRoleGroup().trim().isEmpty()) {
145             to.setRoleGroup(from.getRoleGroup());
146         }
147         if (from.getDescription() != null && !from.getDescription().trim().isEmpty()) {
148             to.setDescription(from.getDescription());
149         }
150
151         if (logger.isDebugEnabled()) {
152                 org.collectionspace.services.authorization.ObjectFactory objectFactory =
153                         new org.collectionspace.services.authorization.ObjectFactory();
154             logger.debug("Merged role on update=" + JaxbUtils.toString(objectFactory.createRole(to), Role.class));
155         }
156         
157         return to;
158     }
159     
160     @Override
161     public void completeCreate(DocumentWrapper<Role> wrapDoc) throws Exception {
162         Role role = wrapDoc.getWrappedObject();
163         //
164         // If there are perms in the payload, create the required role/perm relationships.
165         //
166         List<PermissionValue> permValueList = role.getPermission();
167         if (permValueList != null && permValueList.size() > 0) {
168                 //
169                 // To prevent new Permissions being created (especially low-level Spring Security perms), we'll first flush the current
170                 // JPA context to ensure our Role can be successfully persisted.
171                 //
172                 TransactionContext jpaTransactionContext = this.getServiceContext().getCurrentTransactionContext();
173                 jpaTransactionContext.flush();
174                 
175                 // create and persist a permrole instance
176                 // The caller of this method needs to ensure a valid and active EM (EntityManager) instance is in the Service context
177                 RoleValue roleValue = RoleFactory.createRoleValueInstance(role);
178                 PermissionRole permRole = PermissionRoleFactory.createPermissionRoleInstance(SubjectType.PERMISSION, roleValue,
179                                 permValueList, true, true);
180             PermissionRoleSubResource subResource =
181                     new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
182             subResource.createPermissionRole(getServiceContext(), permRole, SubjectType.PERMISSION);
183         }
184
185     }
186
187     @Override
188     public void completeUpdate(DocumentWrapper<Role> wrapDoc) throws Exception {
189         Role updatedRole = wrapDoc.getWrappedObject();
190         getServiceContext().setOutput(updatedRole);
191         sanitize(updatedRole);
192     }
193
194     @Override
195     public void handleGet(DocumentWrapper<Role> wrapDoc) throws Exception {
196         setCommonPart(extractCommonPart(wrapDoc));
197         sanitize(getCommonPart());
198         getServiceContext().setOutput(role);
199     }
200
201     @Override
202     public void handleGetAll(DocumentWrapper<List<Role>> wrapDoc) throws Exception {
203         RolesList rolesList = extractCommonPartList(wrapDoc);
204         setCommonPartList(rolesList);
205         getServiceContext().setOutput(getCommonPartList());
206     }
207
208         @Override
209     public Role extractCommonPart(
210             DocumentWrapper<Role> wrapDoc)
211             throws Exception {
212         Role role = wrapDoc.getWrappedObject();
213         
214         String includePermsQueryParamValue = (String) getServiceContext().getQueryParams().getFirst(RoleClient.INCLUDE_PERMS_QP);
215         boolean includePerms = Tools.isTrue(includePermsQueryParamValue);
216         if (includePerms) {
217                 PermissionRoleSubResource permRoleResource =
218                         new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
219                 PermissionRole permRole = permRoleResource.getPermissionRole(getServiceContext(), role.getCsid(), SubjectType.PERMISSION);
220                 role.setPermission(permRole.getPermission());
221         }
222     
223         return role;
224     }
225
226     @Override
227     public void fillCommonPart(Role obj, DocumentWrapper<Role> wrapDoc)
228             throws Exception {
229         throw new UnsupportedOperationException("operation not relevant for AccountDocumentHandler");
230     }
231
232     /*
233      * See https://issues.collectionspace.org/browse/DRYD-181
234      * 
235      * For backward compatibility, we could not change the role list to be a child class of AbstractCommonList.  This
236      * would have change the result payload and would break existing API clients.  So the best we can do, it treat
237      * the role list payload as a special case and return the paging information.
238      * 
239      */
240         protected RolesList extractPagingInfoForRoles(RolesList roleList, DocumentWrapper<List<Role>> wrapDoc)
241             throws Exception {
242
243         DocumentFilter docFilter = this.getDocumentFilter();
244         long pageSize = docFilter.getPageSize();
245         long pageNum = pageSize != 0 ? docFilter.getOffset() / pageSize : pageSize;
246         // set the page size and page number
247         roleList.setPageNum(pageNum);
248         roleList.setPageSize(pageSize);
249         List<Role> docList = wrapDoc.getWrappedObject();
250         // Set num of items in list. this is useful to our testing framework.
251         roleList.setItemsInPage(docList.size());
252         // set the total result size
253         roleList.setTotalItems(docFilter.getTotalItemsResult());
254
255         return roleList;
256     }
257         
258     @Override
259     public RolesList extractCommonPartList(
260             DocumentWrapper<List<Role>> wrapDoc) throws Exception {
261
262         RolesList rolesList = extractPagingInfoForRoles(new RolesList(), wrapDoc);        
263         List<Role> list = new ArrayList<Role>();
264         rolesList.setRole(list);
265         for (Role role : wrapDoc.getWrappedObject()) {
266             sanitize(role);
267             list.add(role);
268         }
269         
270         return rolesList;
271     }
272
273     @Override
274     public Role getCommonPart() {
275         return role;
276     }
277
278     @Override
279     public void setCommonPart(Role role) {
280         this.role = role;
281     }
282
283     @Override
284     public RolesList getCommonPartList() {
285         return rolesList;
286     }
287
288     @Override
289     public void setCommonPartList(RolesList rolesList) {
290         this.rolesList = rolesList;
291     }
292
293     @Override
294     public String getQProperty(
295             String prop) {
296         return null;
297     }
298
299     @Override
300     public DocumentFilter createDocumentFilter() {
301         DocumentFilter filter = new RoleJpaFilter(this.getServiceContext());
302         return filter;
303     }
304
305     /**
306      * sanitize removes data not needed to be sent to the consumer
307      * @param roleFound
308      */
309     private void sanitize(Role role) {
310         if (!SecurityUtils.isCSpaceAdmin()) {
311             // role.setTenantId(null); // REM - There's no reason for hiding the tenant ID is there?
312         }
313     }
314
315     private void setTenant(Role role) {
316         //set tenant only if not available from input
317         if (role.getTenantId() == null || role.getTenantId().isEmpty()) {
318             role.setTenantId(getServiceContext().getTenantId());
319         }
320     }
321 }