001: /*******************************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *******************************************************************************/package org.ofbiz.content.content;
019:
020: import java.util.ArrayList;
021: import java.util.HashMap;
022: import java.util.List;
023: import java.util.Map;
024:
025: import org.ofbiz.base.util.Debug;
026: import org.ofbiz.base.util.StringUtil;
027: import org.ofbiz.base.util.UtilMisc;
028: import org.ofbiz.base.util.UtilValidate;
029: import org.ofbiz.entity.GenericDelegator;
030: import org.ofbiz.entity.GenericEntityException;
031: import org.ofbiz.entity.GenericValue;
032: import org.ofbiz.entityext.permission.EntityPermissionChecker;
033: import org.ofbiz.security.Security;
034: import org.ofbiz.service.DispatchContext;
035: import org.ofbiz.service.ModelService;
036: import org.ofbiz.service.ServiceUtil;
037: import org.ofbiz.service.GenericServiceException;
038: import org.ofbiz.service.LocalDispatcher;
039:
040: /**
041: * ContentPermissionServices Class
042: *
043: * Services for granting operation permissions on Content entities in a data-driven manner.
044: */
045: public class ContentPermissionServices {
046:
047: public static final String module = ContentPermissionServices.class
048: .getName();
049:
050: public ContentPermissionServices() {
051: }
052:
053: /**
054: * checkContentPermission
055: *
056: *@param dctx The DispatchContext that this service is operating in
057: *@param context Map containing the input parameters
058: *@return Map with the result of the service, the output parameters
059: *
060: * This service goes thru a series of test to determine if the user has
061: * authority to performed anyone of the passed in target operations.
062: *
063: * It expects a Content entity in "currentContent"
064: * It expects a list of contentOperationIds in "targetOperationList" rather
065: * than a scalar because it is thought that sometimes more than one operation
066: * would fit the situation.
067: * Similarly, it expects a list of contentPurposeTypeIds in "contentPurposeList".
068: * Again, normally there will just be one, but it is possible that a Content
069: * entity could have multiple purposes associated with it.
070: * The userLogin GenericValue is also required.
071: * A list of roleTypeIds is also possible.
072: *
073: * The basic sequence of testing events is:
074: * First the ContentPurposeOperation table is checked to see if there are any
075: * entries with matching purposes (and operations) with no roleTypeId (ie. _NA_).
076: * This is done because it would be the most common scenario and is quick to check.
077: *
078: * Secondly, the CONTENTMGR permission is checked.
079: *
080: * Thirdly, the ContentPurposeOperation table is rechecked to see if there are
081: * any conditions with roleTypeIds that match associated ContentRoles tied to the
082: * user.
083: * If a Party of "PARTY_GROUP" type is found, the PartyRelationship table is checked
084: * to see if the current user is linked to that group.
085: *
086: * If no match is found to this point and the current Content entity has a value for
087: * ownerContentId, then the last step is recusively applied, using the ContentRoles
088: * associated with the ownerContent entity.
089: */
090: public static Map checkContentPermission(DispatchContext dctx,
091: Map context) {
092: Debug
093: .logWarning(
094: new Exception(),
095: "This service has been depricated in favor of [genericContentPermission]",
096: module);
097:
098: Security security = dctx.getSecurity();
099: GenericDelegator delegator = dctx.getDelegator();
100: String statusId = (String) context.get("statusId");
101: String privilegeEnumId = (String) context
102: .get("privilegeEnumId");
103: GenericValue content = (GenericValue) context
104: .get("currentContent");
105: Boolean bDisplayFailCond = (Boolean) context
106: .get("displayFailCond");
107: boolean displayFailCond = false;
108: if (bDisplayFailCond != null && bDisplayFailCond.booleanValue()) {
109: displayFailCond = true;
110: }
111: Debug.logInfo("displayFailCond(0):" + displayFailCond, "");
112: Boolean bDisplayPassCond = (Boolean) context
113: .get("displayPassCond");
114: boolean displayPassCond = false;
115: if (bDisplayPassCond != null && bDisplayPassCond.booleanValue()) {
116: displayPassCond = true;
117: }
118: Debug.logInfo("displayPassCond(0):" + displayPassCond, "");
119: Map results = new HashMap();
120: String contentId = null;
121: if (content != null)
122: contentId = content.getString("contentId");
123: GenericValue userLogin = (GenericValue) context
124: .get("userLogin");
125: String partyId = (String) context.get("partyId");
126: if (UtilValidate.isEmpty(partyId)) {
127: String passedUserLoginId = (String) context
128: .get("userLoginId");
129: if (UtilValidate.isNotEmpty(passedUserLoginId)) {
130: try {
131: userLogin = delegator.findByPrimaryKeyCache(
132: "UserLogin", UtilMisc.toMap("userLoginId",
133: passedUserLoginId));
134: if (userLogin != null) {
135: partyId = userLogin.getString("partyId");
136: }
137: } catch (GenericEntityException e) {
138: ServiceUtil.returnError(e.getMessage());
139: }
140: }
141: }
142: if (UtilValidate.isEmpty(partyId) && userLogin != null) {
143: partyId = userLogin.getString("partyId");
144: }
145:
146: // Do entity permission check. This will pass users with administrative permissions.
147: boolean passed = false;
148: // I realized, belatedly, that I wanted to be able to pass parameters in as
149: // strings so this service could be used in an action event directly,
150: // so I had to write this code to handle both list and strings
151: List passedPurposes = (List) context.get("contentPurposeList");
152: String contentPurposeString = (String) context
153: .get("contentPurposeString");
154: //Debug.logInfo("contentPurposeString(b):" + contentPurposeString, "");
155: if (UtilValidate.isNotEmpty(contentPurposeString)) {
156: List purposesFromString = StringUtil.split(
157: contentPurposeString, "|");
158: if (passedPurposes == null) {
159: passedPurposes = new ArrayList();
160: }
161: passedPurposes.addAll(purposesFromString);
162: }
163:
164: EntityPermissionChecker.StdAuxiliaryValueGetter auxGetter = new EntityPermissionChecker.StdAuxiliaryValueGetter(
165: "ContentPurpose", "contentPurposeTypeId", "contentId");
166: // Sometimes permissions need to be checked before an entity is created, so
167: // there needs to be a method for setting a purpose list
168: auxGetter.setList(passedPurposes);
169: //Debug.logInfo("passedPurposes(b):" + passedPurposes, "");
170: List targetOperations = (List) context
171: .get("targetOperationList");
172: //Debug.logInfo("targetOperations(b):" + targetOperations, "");
173: String targetOperationString = (String) context
174: .get("targetOperationString");
175: //Debug.logInfo("targetOperationString(b):" + targetOperationString, "");
176: if (UtilValidate.isNotEmpty(targetOperationString)) {
177: List operationsFromString = StringUtil.split(
178: targetOperationString, "|");
179: if (targetOperations == null) {
180: targetOperations = new ArrayList();
181: }
182: targetOperations.addAll(operationsFromString);
183: }
184: //Debug.logInfo("targetOperations(c):" + targetOperations, "");
185: EntityPermissionChecker.StdPermissionConditionGetter permCondGetter = new EntityPermissionChecker.StdPermissionConditionGetter(
186: "ContentPurposeOperation", "contentOperationId",
187: "roleTypeId", "statusId", "contentPurposeTypeId",
188: "privilegeEnumId");
189: permCondGetter.setOperationList(targetOperations);
190:
191: EntityPermissionChecker.StdRelatedRoleGetter roleGetter = new EntityPermissionChecker.StdRelatedRoleGetter(
192: "Content", "roleTypeId", "contentId", "partyId",
193: "ownerContentId", "ContentRole");
194: //Debug.logInfo("targetOperations(b):" + targetOperations, "");
195: List passedRoles = (List) context.get("roleTypeList");
196: if (passedRoles == null)
197: passedRoles = new ArrayList();
198: String roleTypeString = (String) context.get("roleTypeString");
199: if (UtilValidate.isNotEmpty(roleTypeString)) {
200: List rolesFromString = StringUtil
201: .split(roleTypeString, "|");
202: passedRoles.addAll(rolesFromString);
203: }
204: roleGetter.setList(passedRoles);
205:
206: String entityAction = (String) context.get("entityOperation");
207: if (entityAction == null)
208: entityAction = "_ADMIN";
209: if (userLogin != null && entityAction != null) {
210: passed = security.hasEntityPermission("CONTENTMGR",
211: entityAction, userLogin);
212: }
213:
214: StringBuffer errBuf = new StringBuffer();
215: String permissionStatus = null;
216: List entityIds = new ArrayList();
217: if (passed) {
218: results.put("permissionStatus", "granted");
219: permissionStatus = "granted";
220: if (displayPassCond) {
221: errBuf.append("\n hasEntityPermission("
222: + entityAction + "): PASSED");
223: }
224:
225: } else {
226: if (displayFailCond) {
227: errBuf.append("\n hasEntityPermission("
228: + entityAction + "): FAILED");
229: }
230:
231: if (content != null)
232: entityIds.add(content);
233: String quickCheckContentId = (String) context
234: .get("quickCheckContentId");
235: if (UtilValidate.isNotEmpty(quickCheckContentId)) {
236: List quickList = StringUtil.split(quickCheckContentId,
237: "|");
238: if (UtilValidate.isNotEmpty(quickList))
239: entityIds.addAll(quickList);
240: }
241: try {
242: boolean check = EntityPermissionChecker
243: .checkPermissionMethod(delegator, partyId,
244: "Content", entityIds, auxGetter,
245: roleGetter, permCondGetter);
246: if (check) {
247: results.put("permissionStatus", "granted");
248: } else {
249: results.put("permissionStatus", "rejected");
250: }
251: } catch (GenericEntityException e) {
252: ServiceUtil.returnError(e.getMessage());
253: }
254: permissionStatus = (String) results.get("permissionStatus");
255: errBuf.append("\n permissionStatus:");
256: errBuf.append(permissionStatus);
257: }
258:
259: if ((permissionStatus.equals("granted") && displayPassCond)
260: || (permissionStatus.equals("rejected") && displayFailCond)) {
261: // Don't show this if passed on 'hasEntityPermission'
262: if (displayFailCond || displayPassCond) {
263: if (!passed) {
264: errBuf.append("\n targetOperations:");
265: errBuf.append(targetOperations);
266:
267: String errMsg = permCondGetter.dumpAsText();
268: errBuf.append("\n");
269: errBuf.append(errMsg);
270: errBuf.append("\n partyId:");
271: errBuf.append(partyId);
272: errBuf.append("\n entityIds:");
273: errBuf.append(entityIds);
274:
275: if (auxGetter != null) {
276: errBuf.append("\n auxList:");
277: errBuf.append(auxGetter.getList());
278: }
279:
280: if (roleGetter != null) {
281: errBuf.append("\n roleList:");
282: errBuf.append(roleGetter.getList());
283: }
284: }
285:
286: }
287: }
288: Debug.logInfo("displayPass/FailCond(0), errBuf:"
289: + errBuf.toString(), "");
290: results.put(ModelService.ERROR_MESSAGE, errBuf.toString());
291: return results;
292: }
293:
294: public static Map checkAssocPermission(DispatchContext dctx,
295: Map context) {
296:
297: Map results = new HashMap();
298: Security security = dctx.getSecurity();
299: GenericDelegator delegator = dctx.getDelegator();
300: LocalDispatcher dispatcher = dctx.getDispatcher();
301: Boolean bDisplayFailCond = (Boolean) context
302: .get("displayFailCond");
303: String contentIdFrom = (String) context.get("contentIdFrom");
304: String contentIdTo = (String) context.get("contentIdTo");
305: GenericValue userLogin = (GenericValue) context
306: .get("userLogin");
307: String entityAction = (String) context.get("entityOperation");
308: if (entityAction == null)
309: entityAction = "_ADMIN";
310: List roleIds = null;
311: String permissionStatus = null;
312:
313: GenericValue contentTo = null;
314: GenericValue contentFrom = null;
315: try {
316: contentTo = delegator.findByPrimaryKeyCache("Content",
317: UtilMisc.toMap("contentId", contentIdTo));
318: contentFrom = delegator.findByPrimaryKeyCache("Content",
319: UtilMisc.toMap("contentId", contentIdFrom));
320: } catch (GenericEntityException e) {
321: return ServiceUtil
322: .returnError("Error in retrieving content To or From. "
323: + e.getMessage());
324: }
325: if (contentTo == null || contentFrom == null) {
326: return ServiceUtil.returnError("contentTo[" + contentTo
327: + "]/From[" + contentFrom + "] is null. ");
328: }
329: Map resultsMap = null;
330: boolean isMatch = false;
331:
332: boolean isMatchTo = false;
333: boolean isMatchFrom = false;
334: Map permResults = new HashMap();
335: String skipPermissionCheck = null;
336:
337: if (skipPermissionCheck == null
338: || skipPermissionCheck.length() == 0
339: || (!skipPermissionCheck.equalsIgnoreCase("true") && !skipPermissionCheck
340: .equalsIgnoreCase("granted"))) {
341: // Use the purposes from the from entity for both cases.
342: List relatedPurposes = EntityPermissionChecker
343: .getRelatedPurposes(contentFrom, null);
344: List relatedPurposesTo = EntityPermissionChecker
345: .getRelatedPurposes(contentTo, relatedPurposes);
346: Map serviceInMap = new HashMap();
347: serviceInMap.put("userLogin", userLogin);
348: serviceInMap.put("targetOperationList", UtilMisc
349: .toList("CONTENT_LINK_TO"));
350: serviceInMap.put("contentPurposeList", relatedPurposesTo);
351: serviceInMap.put("currentContent", contentTo);
352: serviceInMap.put("displayFailCond", bDisplayFailCond);
353:
354: try {
355: permResults = dispatcher.runSync(
356: "checkContentPermission", serviceInMap);
357: } catch (GenericServiceException e) {
358: Debug.logError(e, "Problem checking permissions",
359: "ContentServices");
360: }
361: permissionStatus = (String) permResults
362: .get("permissionStatus");
363: if (permissionStatus == null
364: || !permissionStatus.equals("granted")) {
365: if (bDisplayFailCond != null
366: && bDisplayFailCond.booleanValue()) {
367: String errMsg = (String) permResults
368: .get(ModelService.ERROR_MESSAGE);
369: results.put(ModelService.ERROR_MESSAGE, errMsg);
370: }
371: return results;
372: }
373: serviceInMap.put("currentContent", contentFrom);
374: serviceInMap.put("targetOperationList", UtilMisc
375: .toList("CONTENT_LINK_FROM"));
376: serviceInMap.put("contentPurposeList", relatedPurposes);
377: try {
378: permResults = dispatcher.runSync(
379: "checkContentPermission", serviceInMap);
380: } catch (GenericServiceException e) {
381: Debug.logError(e, "Problem checking permissions",
382: "ContentServices");
383: }
384: permissionStatus = (String) permResults
385: .get("permissionStatus");
386: if (permissionStatus != null
387: && permissionStatus.equals("granted")) {
388: results.put("permissionStatus", "granted");
389: } else {
390: if (bDisplayFailCond != null
391: && bDisplayFailCond.booleanValue()) {
392: String errMsg = (String) permResults
393: .get(ModelService.ERROR_MESSAGE);
394: results.put(ModelService.ERROR_MESSAGE, errMsg);
395: }
396: }
397: } else {
398: results.put("permissionStatus", "granted");
399: }
400: return results;
401: }
402:
403: }
|