]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
27c374cdbc2ed8f31d07b613a0ef12aaba9c6e2e
[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.common.authorization_mgt;
25
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
29 import javax.persistence.EntityManager;
30 import javax.persistence.EntityManagerFactory;
31 import javax.persistence.NoResultException;
32
33 import org.collectionspace.services.common.document.DocumentException;
34 import org.collectionspace.services.common.document.DocumentNotFoundException;
35 import org.collectionspace.services.common.context.ServiceContext;
36 import org.collectionspace.services.common.context.ServiceContextProperties;
37 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
38
39 import org.collectionspace.services.authorization.perms.ActionType;
40 import org.collectionspace.services.authorization.perms.EffectType;
41 import org.collectionspace.services.authorization.perms.Permission;
42 import org.collectionspace.services.authorization.perms.PermissionAction;
43 import org.collectionspace.services.authorization.storage.PermissionStorageConstants;
44 import org.collectionspace.services.authorization.PermissionResource;
45 import org.collectionspace.services.authorization.PermissionRole;
46 import org.collectionspace.services.authorization.PermissionRoleRel;
47 import org.collectionspace.services.authorization.PermissionValue;
48 import org.collectionspace.services.authorization.RoleValue;
49 import org.collectionspace.services.authorization.SubjectType;
50
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 // TODO: Auto-generated Javadoc
55 /**
56  * The Class PermissionRoleUtil.
57  *
58  * @author
59  */
60 public class PermissionRoleUtil {
61
62     static final Logger logger = LoggerFactory.getLogger(PermissionRoleUtil.class);
63
64     /**
65      * Gets the relation subject.
66      *
67      * @param ctx the ctx
68      * @return the relation subject
69      */
70     static public SubjectType getRelationSubject(ServiceContext ctx) {
71         Object o = ctx.getProperty(ServiceContextProperties.SUBJECT);
72         if (o == null) {
73             throw new IllegalArgumentException(ServiceContextProperties.SUBJECT
74                     + " property is missing in context "
75                     + ctx.toString());
76         }
77         return (SubjectType) o;
78     }
79
80     /**
81      * Gets the relation subject.
82      *
83      * @param ctx the ctx
84      * @param pr the pr
85      * @return the relation subject
86      */
87     static public SubjectType getRelationSubject(ServiceContext ctx, PermissionRole pr) {
88         SubjectType subject = pr.getSubject();
89         if (subject == null) {
90             //it is not required to give subject as URI determines the subject
91             subject = getRelationSubject(ctx);
92         }
93         return subject;
94     }
95
96     /**
97      * buildPermissionRoleRel builds persistent relationship entities from given
98      * permissionrole.
99      *
100      * @param pr permissionrole
101      * @param subject the subject
102      * @param prrl persistent entities built are inserted into this list
103      * @param toDelete the to delete
104      */
105     static public void buildPermissionRoleRel(EntityManager em, 
106                 PermissionRole pr,
107                 SubjectType subject,
108                 List<PermissionRoleRel> prrl,
109                 boolean handleDelete,
110                 String tenantId) throws Exception {
111         
112         if (subject.equals(SubjectType.ROLE)) {
113                 List<PermissionValue> permissionValues = pr.getPermission();
114                 if (permissionValues != null && permissionValues.size() > 0) {
115                     PermissionValue pv = permissionValues.get(0);
116                     for (RoleValue rv : pr.getRole()) {
117                         PermissionRoleRel prr = buildPermissonRoleRel(em, pv, rv, subject, handleDelete, tenantId);
118                         prrl.add(prr);
119                     }
120                 }
121         } else if (subject.equals(SubjectType.PERMISSION)) {
122                 List<RoleValue> roleValues = pr.getRole();
123                 if (roleValues != null && roleValues.size() > 0) {
124                     RoleValue rv = roleValues.get(0);
125                     for (PermissionValue pv : pr.getPermission()) {
126                         PermissionRoleRel prr = buildPermissonRoleRel(em, pv, rv, subject, handleDelete, tenantId);
127                         prrl.add(prr);
128                     }
129                 }
130         }
131     }
132     
133     static public void buildPermissionRoleRel( 
134                 PermissionRole pr,
135                 SubjectType subject,
136                 List<PermissionRoleRel> prrl,
137                 boolean handleDelete,
138                 String tenantId) throws Exception {
139         EntityManagerFactory emf = null;
140         EntityManager em = null;
141         try {
142             emf = JpaStorageUtils.getEntityManagerFactory(JpaStorageUtils.CS_PERSISTENCE_UNIT);
143             em = emf.createEntityManager();
144             em.getTransaction().begin();
145             
146             buildPermissionRoleRel(em, pr, subject, prrl, handleDelete, tenantId);
147             
148             em.getTransaction().commit();
149                 em.close();            
150         } catch (Exception e) {
151             if (em != null && em.getTransaction().isActive()) {
152                 em.getTransaction().rollback();
153             }
154             if (logger.isDebugEnabled()) {
155                 logger.debug("Caught exception ", e);
156             }
157             throw e;
158         } finally {
159             if (em != null) {
160                 JpaStorageUtils.releaseEntityManagerFactory(emf);
161             }
162         }
163     }    
164
165     /*
166      * Try to find a persisted Permission record using a PermissionValue instance.
167      *
168      */
169     static private Permission lookupPermission(EntityManager em, PermissionValue permissionValue, String tenantId) {
170         Permission result = null;
171         
172         String actionGroup = permissionValue.getActionGroup() != null ? permissionValue.getActionGroup().trim() : null;
173         String resourceName = permissionValue.getResourceName() != null ? permissionValue.getResourceName().trim() : null;
174         String permissionId = permissionValue.getPermissionId() != null ? permissionValue.getPermissionId().trim() : null;
175         //
176         // If we have a permission ID, use it to try to lookup the persisted permission
177         //
178         if (permissionId != null && !permissionId.isEmpty()) {
179                 try {
180                         result = (Permission)JpaStorageUtils.getEntity(em, permissionId, Permission.class);
181                 } catch (Throwable e) {
182                         String msg = String.format("Searched for but couldn't find a permission with CSID='%s'.",
183                                         permissionId);
184                         logger.trace(msg);
185                 }
186         } else if ((resourceName != null && !resourceName.isEmpty()) && 
187                         (actionGroup != null && !actionGroup.isEmpty())) {
188                 //
189                 // If there was no permission ID, then we can try to find the permission with the resource name and action group tuple
190                 //
191                 try {
192                         result = (Permission)JpaStorageUtils.getEntityByDualKeys(em, 
193                                         Permission.class.getName(),
194                                         PermissionStorageConstants.RESOURCE_NAME, permissionValue.getResourceName(), 
195                                         PermissionStorageConstants.ACTION_GROUP, permissionValue.getActionGroup(),
196                                         tenantId);
197                 } catch (NoResultException e) {
198                         String msg = String.format("Searched for but couldn't find a permission for resource='%s', action group='%s', and tenant ID='%s'.",
199                                         permissionValue.getResourceName(), permissionValue.getActionGroup(), tenantId);
200                         logger.trace(msg);
201                 }
202         } else {
203                 String errMsg = String.format("Couldn't perform lookup of permission.  Not enough information provided.  Lookups requires a permission CSID or a resource name and action group tuple.  The provided information was permission ID='%s', resourceName='%s', and actionGroup='%s'.",
204                                 permissionId, resourceName, actionGroup);
205                 logger.warn(errMsg);
206         }
207         
208         return result;
209     }
210     
211     /**
212      * Builds a permisson role relationship for either 'create' or 'delete'
213      *
214      * @param pv the pv (currently using only the ID)
215      * @param rv the rv (currently using only the ID)
216      * @param handleDelete the handle delete
217      * @return the permission role rel
218      * @throws DocumentException 
219      */
220     static private PermissionRoleRel buildPermissonRoleRel(EntityManager em, PermissionValue permissionValue,
221                 RoleValue roleValue,
222                 SubjectType subject,
223                 boolean handleDelete,  // if 'true' then we're deleting not building a permission-role record
224                 String tenantId) throws DocumentException {
225
226         PermissionRoleRel result = null;
227         Permission permission = lookupPermission(em, permissionValue, tenantId);
228         
229         //
230         // If we couldn't find an existing permission and we're not processing a DELETE request, we need to create
231         // a new permission.
232         //
233         if (permission == null && handleDelete == false) {
234                 permission = new Permission();
235                 permission.setResourceName(permissionValue.getResourceName());
236                 permission.setActionGroup(permissionValue.getActionGroup());
237                 permission.setEffect(EffectType.PERMIT); // By default, CollectionSpace currently (11/2017) supports only PERMIT
238                 List<PermissionAction> actionList = createPermActionList(permissionValue.getActionGroup());
239                 permission.setAction(actionList);
240                 permission = createPermission(permission);
241                 if (permission == null) {
242                         String errMsg = "Could not create new permission for new permission-role relationship.";
243                         throw new DocumentException(errMsg);
244                 }
245         }
246         
247         //
248         // Since our permissionValue may not have been supplied by the client with an ID, we need
249         // to add it now.
250         //
251         if (permissionValue.getPermissionId() == null || permissionValue.getPermissionId().trim().isEmpty()) {
252                 permissionValue.setPermissionId(permission.getCsid());
253         }
254         
255         //
256         // Create the permission-role to persist
257         //
258         result = new PermissionRoleRel();
259         result.setPermissionId(permission.getCsid());
260         result.setPermissionResource(permission.getResourceName());
261         result.setActionGroup(permission.getActionGroup());
262         result.setRoleId(roleValue.getRoleId());
263         result.setRoleName(roleValue.getRoleName());
264         
265         //
266         // For 'delete' we need to set the hjid of the existing relstionship
267         //
268         String relationshipId = null;
269         if (subject.equals(SubjectType.ROLE) == true) {
270                 relationshipId = roleValue.getRoleRelationshipId();
271         } else if (subject.equals(SubjectType.PERMISSION) == true) {
272                 relationshipId = permissionValue.getPermRelationshipId();
273         }
274         if (relationshipId != null && handleDelete == true) {
275                 result.setHjid(Long.parseLong(relationshipId));  // set this so we can convince JPA to del the relation
276         }
277         
278         return result;
279     }
280
281     private static Permission createPermission(Permission permission) {
282                 Permission result = null;
283                 
284                 PermissionResource permissionResource = new PermissionResource();  // Get the PermissionResource singleton instance (RESTEasy ensures it is a singleton)
285                 result = permissionResource.createPermissionFromInstance(permission);
286                 
287                 return result;
288         }
289
290         private static List<PermissionAction> createPermActionList(String actionGroup) throws DocumentException {
291         ArrayList<PermissionAction> result = new ArrayList<PermissionAction>();
292         
293         for (char c : actionGroup.toUpperCase().toCharArray()) {
294                 PermissionAction permAction = new PermissionAction();
295                 switch (c) {
296                         case 'C':
297                                 permAction.setName(ActionType.CREATE);
298                                 break;
299                                 
300                         case 'R':
301                                 permAction.setName(ActionType.READ);
302                                 break;
303                                 
304                         case 'U':
305                                 permAction.setName(ActionType.UPDATE);
306                                 break;
307                                 
308                         case 'D':
309                                 permAction.setName(ActionType.DELETE);
310                                 break;
311                                 
312                         case 'L':
313                                 permAction.setName(ActionType.SEARCH);
314                                 break;
315                                 
316                         default:
317                                 String errMsg = String.format("Illegal action group token '%c' in permission action group '%s'.",
318                                                 c, actionGroup);
319                                 throw new DocumentException(errMsg);
320                 }
321                 
322                 if (result.add(permAction) == false) {
323                         String warnMsg = String.format("Illegal or duplicate action group token '%c' in permission action group '%s'.",
324                                         c, actionGroup);
325                         logger.warn(warnMsg);
326                 }
327         }
328         
329                 return result;
330         }
331
332         /**
333      * Checks if is invalid tenant.
334      *
335      * @param tenantId the tenant id
336      * @param msgBldr the msg bldr
337      * @return true, if is invalid tenant
338      */
339     static boolean isInvalidTenant(String tenantId, StringBuilder msgBldr) {
340         boolean invalid = false;
341
342         if (tenantId == null || tenantId.isEmpty()) {
343             invalid = true;
344             msgBldr.append("\n tenant : tenantId is missing");
345         }
346         String whereClause = "where id = :id";
347         HashMap<String, Object> params = new HashMap<String, Object>();
348         params.put("id", tenantId);
349
350         Object tenantFound = JpaStorageUtils.getEntity(
351                 "org.collectionspace.services.account.Tenant", whereClause, params);
352         if (tenantFound == null) {
353             invalid = true;
354             msgBldr.append("\n tenant : tenantId=" + tenantId
355                     + " not found");
356         }
357         return invalid;
358     }
359 }