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:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
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.
24 package org.collectionspace.services.authorization.storage;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.UUID;
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;
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.jpa.JpaDocumentHandler;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
54 * Document handler for Role
57 @SuppressWarnings("unchecked")
58 public class RoleDocumentHandler
59 extends JpaDocumentHandler<Role, RolesList, Role, List<Role>> {
60 private final Logger logger = LoggerFactory.getLogger(RoleDocumentHandler.class);
62 private RolesList rolesList;
65 public void handleCreate(DocumentWrapper<Role> wrapDoc) throws Exception {
66 String id = UUID.randomUUID().toString();
67 Role role = wrapDoc.getWrappedObject();
69 // Synthesize the display name if it was not passed in.
70 String displayName = role.getDisplayName();
71 boolean displayNameEmpty = true;
72 if (displayName != null) {
73 displayNameEmpty = displayName.trim().isEmpty();
75 if (displayNameEmpty == true) {
76 role.setDisplayName(role.getRoleName());
80 role.setRoleName(RoleClient.getBackendRoleName(role.getRoleName(), role.getTenantId()));
82 // We do not allow creation of locked roles through the services.
83 role.setMetadataProtection(null);
84 role.setPermsProtection(null);
87 @SuppressWarnings("rawtypes")
89 public void handleUpdate(DocumentWrapper<Role> wrapDoc) throws Exception {
90 Role roleFound = wrapDoc.getWrappedObject();
91 Role roleReceived = getCommonPart();
92 // If marked as metadata immutable, do not do update
93 if (!RoleClient.IMMUTABLE.equals(roleFound.getMetadataProtection())) {
95 .setRoleName(RoleClient.getBackendRoleName(roleReceived.getRoleName(), roleFound.getTenantId()));
96 merge(roleReceived, roleFound);
99 // Update perms is supplied.
101 ServiceContext ctx = this.getServiceContext();
102 List<PermissionValue> permValueList = roleReceived.getPermission();
103 if (permValueList != null && permValueList.size() > 0) {
104 PermissionRoleSubResource subResource =
105 new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
107 // First, delete the existing permroles
109 subResource.deletePermissionRole(ctx, roleFound.getCsid(), SubjectType.PERMISSION);
111 // Next, create the new permroles
113 RoleValue roleValue = RoleFactory.createRoleValueInstance(roleFound);
114 PermissionRole permRole = PermissionRoleFactory.createPermissionRoleInstance(SubjectType.PERMISSION, roleValue,
115 permValueList, true, true);
116 subResource.createPermissionRole(ctx, permRole, SubjectType.PERMISSION);
118 // Finally, set the updated perm list in the result
120 PermissionRole newPermRole = subResource.getPermissionRole(ctx, roleFound.getCsid(), SubjectType.PERMISSION);
121 roleFound.setPermission(newPermRole.getPermission());
126 * Merge fields manually from 'from' to the 'to' role
127 * -this method is created due to inefficiency of JPA EM merge
130 * @return merged role
132 private Role merge(Role from, Role to) throws Exception {
133 // A role's name cannot be changed
134 if (!(from.getRoleName().equalsIgnoreCase(to.getRoleName()))) {
135 String msg = "Role name cannot be changed " + to.getRoleName();
137 throw new BadRequestException(msg);
140 if (from.getDisplayName() != null && !from.getDisplayName().trim().isEmpty() ) {
141 to.setDisplayName(from.getDisplayName());
143 if (from.getRoleGroup() != null && !from.getRoleGroup().trim().isEmpty()) {
144 to.setRoleGroup(from.getRoleGroup());
146 if (from.getDescription() != null && !from.getDescription().trim().isEmpty()) {
147 to.setDescription(from.getDescription());
150 if (logger.isDebugEnabled()) {
151 org.collectionspace.services.authorization.ObjectFactory objectFactory =
152 new org.collectionspace.services.authorization.ObjectFactory();
153 logger.debug("Merged role on update=" + JaxbUtils.toString(objectFactory.createRole(to), Role.class));
160 public void completeCreate(DocumentWrapper<Role> wrapDoc) throws Exception {
161 Role role = wrapDoc.getWrappedObject();
163 // If there are perms in the payload, create the required role/perm relationships.
165 List<PermissionValue> permValueList = role.getPermission();
166 if (permValueList != null && permValueList.size() > 0) {
167 // create and persist a permrole instance
168 // The caller of this method needs to ensure a valid and active EM (EntityManager) instance is in the Service context
169 RoleValue roleValue = RoleFactory.createRoleValueInstance(role);
170 PermissionRole permRole = PermissionRoleFactory.createPermissionRoleInstance(SubjectType.PERMISSION, roleValue,
171 permValueList, true, true);
172 PermissionRoleSubResource subResource =
173 new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
174 subResource.createPermissionRole(getServiceContext(), permRole, SubjectType.PERMISSION);
180 public void completeUpdate(DocumentWrapper<Role> wrapDoc) throws Exception {
181 Role updatedRole = wrapDoc.getWrappedObject();
182 getServiceContext().setOutput(updatedRole);
183 sanitize(updatedRole);
187 public void handleGet(DocumentWrapper<Role> wrapDoc) throws Exception {
188 setCommonPart(extractCommonPart(wrapDoc));
189 sanitize(getCommonPart());
190 getServiceContext().setOutput(role);
194 public void handleGetAll(DocumentWrapper<List<Role>> wrapDoc) throws Exception {
195 RolesList rolesList = extractCommonPartList(wrapDoc);
196 setCommonPartList(rolesList);
197 getServiceContext().setOutput(getCommonPartList());
201 public Role extractCommonPart(
202 DocumentWrapper<Role> wrapDoc)
204 Role role = wrapDoc.getWrappedObject();
206 String includePermsQueryParamValue = (String) getServiceContext().getQueryParams().getFirst(RoleClient.INCLUDE_PERMS_QP);
207 boolean includePerms = Tools.isTrue(includePermsQueryParamValue);
209 PermissionRoleSubResource permRoleResource =
210 new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
211 PermissionRole permRole = permRoleResource.getPermissionRole(getServiceContext(), role.getCsid(), SubjectType.PERMISSION);
212 role.setPermission(permRole.getPermission());
219 public void fillCommonPart(Role obj, DocumentWrapper<Role> wrapDoc)
221 throw new UnsupportedOperationException("operation not relevant for AccountDocumentHandler");
225 * See https://issues.collectionspace.org/browse/DRYD-181
227 * For backward compatibility, we could not change the role list to be a child class of AbstractCommonList. This
228 * would have change the result payload and would break existing API clients. So the best we can do, it treat
229 * the role list payload as a special case and return the paging information.
232 protected RolesList extractPagingInfoForRoles(RolesList roleList, DocumentWrapper<List<Role>> wrapDoc)
235 DocumentFilter docFilter = this.getDocumentFilter();
236 long pageSize = docFilter.getPageSize();
237 long pageNum = pageSize != 0 ? docFilter.getOffset() / pageSize : pageSize;
238 // set the page size and page number
239 roleList.setPageNum(pageNum);
240 roleList.setPageSize(pageSize);
241 List<Role> docList = wrapDoc.getWrappedObject();
242 // Set num of items in list. this is useful to our testing framework.
243 roleList.setItemsInPage(docList.size());
244 // set the total result size
245 roleList.setTotalItems(docFilter.getTotalItemsResult());
251 public RolesList extractCommonPartList(
252 DocumentWrapper<List<Role>> wrapDoc) throws Exception {
254 RolesList rolesList = extractPagingInfoForRoles(new RolesList(), wrapDoc);
255 List<Role> list = new ArrayList<Role>();
256 rolesList.setRole(list);
257 for (Role role : wrapDoc.getWrappedObject()) {
266 public Role getCommonPart() {
271 public void setCommonPart(Role role) {
276 public RolesList getCommonPartList() {
281 public void setCommonPartList(RolesList rolesList) {
282 this.rolesList = rolesList;
286 public String getQProperty(
292 public DocumentFilter createDocumentFilter() {
293 DocumentFilter filter = new RoleJpaFilter(this.getServiceContext());
298 * sanitize removes data not needed to be sent to the consumer
301 private void sanitize(Role role) {
302 if (!SecurityUtils.isCSpaceAdmin()) {
303 // role.setTenantId(null); // REM - There's no reason for hiding the tenant ID is there?
307 private void setTenant(Role role) {
308 //set tenant only if not available from input
309 if (role.getTenantId() == null || role.getTenantId().isEmpty()) {
310 role.setTenantId(getServiceContext().getTenantId());