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.account.AccountsCommonList;
31 import org.collectionspace.services.authorization.PermissionRole;
32 import org.collectionspace.services.authorization.PermissionRoleSubResource;
33 import org.collectionspace.services.authorization.PermissionValue;
34 import org.collectionspace.services.authorization.Role;
35 import org.collectionspace.services.authorization.RoleValue;
36 import org.collectionspace.services.authorization.RolesList;
37 import org.collectionspace.services.authorization.SubjectType;
39 import org.collectionspace.services.client.PermissionRoleFactory;
40 import org.collectionspace.services.client.RoleClient;
41 import org.collectionspace.services.client.RoleFactory;
42 import org.collectionspace.services.common.api.Tools;
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;
49 import org.collectionspace.services.jaxb.AbstractCommonList;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
54 * Document handler for Role
57 public class RoleDocumentHandler
58 extends JpaDocumentHandler<Role, RolesList, Role, List<Role>> {
59 private final Logger logger = LoggerFactory.getLogger(RoleDocumentHandler.class);
61 private RolesList rolesList;
64 public void handleCreate(DocumentWrapper<Role> wrapDoc) throws Exception {
65 String id = UUID.randomUUID().toString();
66 Role role = wrapDoc.getWrappedObject();
68 // Synthesize the display name if it was not passed in.
69 String displayName = role.getDisplayName();
70 boolean displayNameEmpty = true;
71 if (displayName != null) {
72 displayNameEmpty = displayName.trim().isEmpty();
74 if (displayNameEmpty == true) {
75 role.setDisplayName(role.getRoleName());
79 role.setRoleName(RoleClient.getBackendRoleName(role.getRoleName(), role.getTenantId()));
81 // We do not allow creation of locked roles through the services.
82 role.setMetadataProtection(null);
83 role.setPermsProtection(null);
87 public void completeCreate(DocumentWrapper<Role> wrapDoc) throws Exception {
88 Role role = wrapDoc.getWrappedObject();
89 List<PermissionValue> permValueList = role.getPermission();
90 if (permValueList != null && permValueList.size() > 0) {
91 // create and persist a permrole instance
92 // The caller of this method needs to ensure a valid and active EM (EntityManager) instance is in the Service context
93 RoleValue roleValue = RoleFactory.createRoleValueInstance(role);
94 PermissionRole permRole = PermissionRoleFactory.createPermissionRoleInstance(SubjectType.PERMISSION, roleValue,
95 permValueList, true, true);
96 PermissionRoleSubResource subResource =
97 new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
98 String permrolecsid = subResource.createPermissionRole(permRole, SubjectType.PERMISSION);
103 public void handleUpdate(DocumentWrapper<Role> wrapDoc) throws Exception {
104 Role roleFound = wrapDoc.getWrappedObject();
105 Role roleReceived = getCommonPart();
106 // If marked as metadata immutable, do not do update
107 if (!RoleClient.IMMUTABLE.equals(roleFound.getMetadataProtection())) {
109 .setRoleName(RoleClient.getBackendRoleName(roleReceived.getRoleName(), roleFound.getTenantId()));
110 merge(roleReceived, roleFound);
113 // Update perms is supplied.
115 List<PermissionValue> permValueList = roleReceived.getPermission();
116 if (permValueList != null) {
117 PermissionRoleSubResource subResource =
118 new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
120 // First, delete the existing permroles
122 subResource.deletePermissionRole(roleFound.getCsid(), SubjectType.PERMISSION);
124 // Next, create the new permroles
126 RoleValue roleValue = RoleFactory.createRoleValueInstance(roleFound);
127 PermissionRole permRole = PermissionRoleFactory.createPermissionRoleInstance(SubjectType.PERMISSION, roleValue,
128 permValueList, true, true);
129 subResource.createPermissionRole(permRole, SubjectType.PERMISSION);
131 // Finally, set the updated perm list in the result
133 PermissionRole newPermRole = subResource.getPermissionRole(roleFound.getCsid(), SubjectType.PERMISSION);
134 roleFound.setPermission(newPermRole.getPermission());
139 * Merge fields manually from 'from' to the 'to' role
140 * -this method is created due to inefficiency of JPA EM merge
143 * @return merged role
145 private Role merge(Role from, Role to) throws Exception {
146 // A role's name cannot be changed
147 if (!(from.getRoleName().equalsIgnoreCase(to.getRoleName()))) {
148 String msg = "Role name cannot be changed " + to.getRoleName();
150 throw new BadRequestException(msg);
153 if (from.getDisplayName() != null && !from.getDisplayName().trim().isEmpty() ) {
154 to.setDisplayName(from.getDisplayName());
156 if (from.getRoleGroup() != null && !from.getRoleGroup().trim().isEmpty()) {
157 to.setRoleGroup(from.getRoleGroup());
159 if (from.getDescription() != null && !from.getDescription().trim().isEmpty()) {
160 to.setDescription(from.getDescription());
163 if (logger.isDebugEnabled()) {
164 org.collectionspace.services.authorization.ObjectFactory objectFactory =
165 new org.collectionspace.services.authorization.ObjectFactory();
166 logger.debug("Merged role on update=" + JaxbUtils.toString(objectFactory.createRole(to), Role.class));
173 public void completeUpdate(DocumentWrapper<Role> wrapDoc) throws Exception {
174 Role updatedRole = wrapDoc.getWrappedObject();
175 getServiceContext().setOutput(updatedRole);
176 sanitize(updatedRole);
180 public void handleGet(DocumentWrapper<Role> wrapDoc) throws Exception {
181 setCommonPart(extractCommonPart(wrapDoc));
182 sanitize(getCommonPart());
183 getServiceContext().setOutput(role);
187 public void handleGetAll(DocumentWrapper<List<Role>> wrapDoc) throws Exception {
188 RolesList rolesList = extractCommonPartList(wrapDoc);
189 setCommonPartList(rolesList);
190 getServiceContext().setOutput(getCommonPartList());
194 public Role extractCommonPart(
195 DocumentWrapper<Role> wrapDoc)
197 Role role = wrapDoc.getWrappedObject();
199 String includePermsQueryParamValue = (String) getServiceContext().getQueryParams().getFirst(RoleClient.INCLUDE_PERMS_QP);
200 boolean includePerms = Tools.isTrue(includePermsQueryParamValue);
202 PermissionRoleSubResource permRoleResource =
203 new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
204 PermissionRole permRole = permRoleResource.getPermissionRole(role.getCsid(), SubjectType.PERMISSION);
205 role.setPermission(permRole.getPermission());
212 public void fillCommonPart(Role obj, DocumentWrapper<Role> wrapDoc)
214 throw new UnsupportedOperationException("operation not relevant for AccountDocumentHandler");
218 * See https://issues.collectionspace.org/browse/DRYD-181
220 * For backward compatibility, we could not change the role list to be a child class of AbstractCommonList. This
221 * would have change the result payload and would break existing API clients. So the best we can do, it treat
222 * the role list payload as a special case and return the paging information.
225 protected RolesList extractPagingInfoForRoles(RolesList roleList, DocumentWrapper<List<Role>> wrapDoc)
228 DocumentFilter docFilter = this.getDocumentFilter();
229 long pageSize = docFilter.getPageSize();
230 long pageNum = pageSize != 0 ? docFilter.getOffset() / pageSize : pageSize;
231 // set the page size and page number
232 roleList.setPageNum(pageNum);
233 roleList.setPageSize(pageSize);
234 List<Role> docList = wrapDoc.getWrappedObject();
235 // Set num of items in list. this is useful to our testing framework.
236 roleList.setItemsInPage(docList.size());
237 // set the total result size
238 roleList.setTotalItems(docFilter.getTotalItemsResult());
244 public RolesList extractCommonPartList(
245 DocumentWrapper<List<Role>> wrapDoc) throws Exception {
247 RolesList rolesList = extractPagingInfoForRoles(new RolesList(), wrapDoc);
248 List<Role> list = new ArrayList<Role>();
249 rolesList.setRole(list);
250 for (Role role : wrapDoc.getWrappedObject()) {
259 public Role getCommonPart() {
264 public void setCommonPart(Role role) {
269 public RolesList getCommonPartList() {
274 public void setCommonPartList(RolesList rolesList) {
275 this.rolesList = rolesList;
279 public String getQProperty(
285 public DocumentFilter createDocumentFilter() {
286 DocumentFilter filter = new RoleJpaFilter(this.getServiceContext());
291 * sanitize removes data not needed to be sent to the consumer
294 private void sanitize(Role role) {
295 if (!SecurityUtils.isCSpaceAdmin()) {
296 // role.setTenantId(null); // REM - There's no reason for hiding the tenant ID is there?
300 private void setTenant(Role role) {
301 //set tenant only if not available from input
302 if (role.getTenantId() == null || role.getTenantId().isEmpty()) {
303 role.setTenantId(getServiceContext().getTenantId());