001: /**
002: * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
003: *
004: * Permission is hereby granted, free of charge, to any person obtaining a copy
005: * of this software and associated documentation files (the "Software"), to deal
006: * in the Software without restriction, including without limitation the rights
007: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008: * copies of the Software, and to permit persons to whom the Software is
009: * furnished to do so, subject to the following conditions:
010: *
011: * The above copyright notice and this permission notice shall be included in
012: * all copies or substantial portions of the Software.
013: *
014: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
020: * SOFTWARE.
021: */package com.liferay.portal.security.permission;
022:
023: import com.liferay.portal.NoSuchResourceException;
024: import com.liferay.portal.kernel.security.permission.PermissionChecker;
025: import com.liferay.portal.kernel.security.permission.PermissionCheckerBag;
026: import com.liferay.portal.kernel.util.GetterUtil;
027: import com.liferay.portal.kernel.util.StringPool;
028: import com.liferay.portal.kernel.util.Validator;
029: import com.liferay.portal.model.Group;
030: import com.liferay.portal.model.Organization;
031: import com.liferay.portal.model.Resource;
032: import com.liferay.portal.model.User;
033: import com.liferay.portal.model.impl.GroupImpl;
034: import com.liferay.portal.model.impl.PortletImpl;
035: import com.liferay.portal.model.impl.ResourceImpl;
036: import com.liferay.portal.model.impl.RoleImpl;
037: import com.liferay.portal.service.GroupLocalServiceUtil;
038: import com.liferay.portal.service.OrganizationLocalServiceUtil;
039: import com.liferay.portal.service.PermissionLocalServiceUtil;
040: import com.liferay.portal.service.ResourceLocalServiceUtil;
041: import com.liferay.portal.service.RoleLocalServiceUtil;
042: import com.liferay.portal.service.UserGroupLocalServiceUtil;
043: import com.liferay.portal.service.UserLocalServiceUtil;
044: import com.liferay.portal.service.permission.PortletPermissionUtil;
045: import com.liferay.portal.util.PropsUtil;
046: import com.liferay.portlet.admin.util.OmniadminUtil;
047: import com.liferay.util.CollectionFactory;
048: import com.liferay.util.UniqueList;
049:
050: import java.io.Serializable;
051:
052: import java.util.ArrayList;
053: import java.util.HashMap;
054: import java.util.Iterator;
055: import java.util.List;
056: import java.util.Map;
057:
058: import javax.portlet.PortletRequest;
059:
060: import org.apache.commons.lang.time.StopWatch;
061: import org.apache.commons.logging.Log;
062: import org.apache.commons.logging.LogFactory;
063:
064: /**
065: * <a href="PermissionCheckerImpl.java.html"><b><i>View Source</i></b></a>
066: *
067: * @author Charles May
068: * @author Brian Wing Shun Chan
069: *
070: */
071: public class PermissionCheckerImpl implements PermissionChecker,
072: Serializable {
073:
074: public static final int USER_CHECK_ALGORITHM = GetterUtil
075: .getInteger(PropsUtil
076: .get(PropsUtil.PERMISSIONS_USER_CHECK_ALGORITHM));
077:
078: public PermissionCheckerImpl() {
079: }
080:
081: public void init(User user, boolean checkGuest) {
082: this .user = user;
083:
084: if (user.isDefaultUser()) {
085: this .defaultUserId = user.getUserId();
086: this .signedIn = false;
087: } else {
088: try {
089: this .defaultUserId = UserLocalServiceUtil
090: .getDefaultUserId(user.getCompanyId());
091: } catch (Exception e) {
092: _log.error(e, e);
093: }
094:
095: this .signedIn = true;
096: }
097:
098: this .checkGuest = checkGuest;
099: }
100:
101: public void recycle() {
102: user = null;
103: defaultUserId = 0;
104: signedIn = false;
105: checkGuest = false;
106: omniadmin = null;
107: companyAdmins.clear();
108: bags.clear();
109: resetValues();
110: }
111:
112: public void setValues(PortletRequest req) {
113:
114: // This method is called in com.liferay.portlet.StrutsPortlet to allow
115: // developers to hook in additiona parameters from the portlet request.
116: // Don't overwrite this method unless you're using Liferay in a 2 tier
117: // environment and don't expect to make remote calls. Remote calls to
118: // service beans will not have any values set from the portlet request.
119:
120: }
121:
122: public void resetValues() {
123: }
124:
125: public User getUser() {
126: return user;
127: }
128:
129: public void setUser(User user) {
130: this .user = user;
131: }
132:
133: public long getUserId() {
134: return user.getUserId();
135: }
136:
137: public boolean isSignedIn() {
138: return signedIn;
139: }
140:
141: public void setSignedIn(boolean signedIn) {
142: this .signedIn = signedIn;
143: }
144:
145: public boolean isCheckGuest() {
146: return checkGuest;
147: }
148:
149: public void setCheckGuest(boolean checkGuest) {
150: this .checkGuest = checkGuest;
151: }
152:
153: public boolean hasPermission(long groupId, String name,
154: long primKey, String actionId) {
155:
156: return hasPermission(groupId, name, String.valueOf(primKey),
157: actionId);
158: }
159:
160: public boolean hasPermission(long groupId, String name,
161: String primKey, String actionId) {
162:
163: StopWatch stopWatch = null;
164:
165: if (_log.isDebugEnabled()) {
166: stopWatch = new StopWatch();
167:
168: stopWatch.start();
169: }
170:
171: Group group = null;
172:
173: // If the current group is staging, the live group should be checked for
174: // permissions instead
175:
176: try {
177: if (groupId > 0) {
178: group = GroupLocalServiceUtil.getGroup(groupId);
179:
180: if (group.isStagingGroup()) {
181: if (primKey.equals(String.valueOf(groupId))) {
182: primKey = String
183: .valueOf(group.getLiveGroupId());
184: }
185:
186: groupId = group.getLiveGroupId();
187: group = group.getLiveGroup();
188: }
189: }
190: } catch (Exception e) {
191: _log.error(e, e);
192: }
193:
194: PermissionCheckerBag bag = getBag(groupId);
195:
196: if (signedIn && (bag == null)) {
197: try {
198:
199: // If we are checking permissions on an object that belongs to a
200: // community, then it's only necessary to check the group that
201: // represents the community and not all the groups that the user
202: // belongs to. This is so because an object cannot belong to
203: // more than one community.
204:
205: List userGroups = new ArrayList();
206: //List userGroups = UserUtil.getGroups(userId);
207:
208: if (groupId > 0) {
209: if (GroupLocalServiceUtil.hasUserGroup(user
210: .getUserId(), groupId)) {
211:
212: userGroups.add(group);
213: }
214: }
215:
216: List userOrgs = getUserOrgs(user.getUserId());
217:
218: List userOrgGroups = GroupLocalServiceUtil
219: .getOrganizationsGroups(userOrgs);
220:
221: List userUserGroups = UserGroupLocalServiceUtil
222: .getUserUserGroups(user.getUserId());
223:
224: List userUserGroupGroups = GroupLocalServiceUtil
225: .getUserGroupsGroups(userUserGroups);
226:
227: List groups = new ArrayList(userGroups.size()
228: + userOrgGroups.size()
229: + userUserGroupGroups.size());
230:
231: groups.addAll(userGroups);
232: groups.addAll(userOrgGroups);
233: groups.addAll(userUserGroupGroups);
234:
235: List roles = null;
236:
237: if ((USER_CHECK_ALGORITHM == 3)
238: || (USER_CHECK_ALGORITHM == 4)) {
239:
240: roles = RoleLocalServiceUtil.getUserRelatedRoles(
241: user.getUserId(), groups);
242:
243: List userGroupRoles = RoleLocalServiceUtil
244: .getUserGroupRoles(user.getUserId(),
245: groupId);
246:
247: roles.addAll(userGroupRoles);
248: } else {
249: roles = new ArrayList();
250: }
251:
252: if (_log.isDebugEnabled()) {
253: _log.debug("Creating bag for " + groupId + " "
254: + name + " " + primKey + " " + actionId
255: + " takes " + stopWatch.getTime() + " ms");
256: }
257:
258: bag = new PermissionCheckerBagImpl(user.getUserId(),
259: userGroups, userOrgs, userOrgGroups,
260: userUserGroupGroups, groups, roles);
261:
262: putBag(groupId, bag);
263: } catch (Exception e) {
264: _log.error(e, e);
265: }
266: }
267:
268: Boolean value = PermissionCacheUtil.hasPermission(user
269: .getUserId(), groupId, name, primKey, actionId);
270:
271: if (value == null) {
272: value = Boolean.valueOf(hasPermissionImpl(groupId, name,
273: primKey, actionId));
274:
275: PermissionCacheUtil.putPermission(user.getUserId(),
276: groupId, name, primKey, actionId, value);
277:
278: if (_log.isDebugEnabled()) {
279: _log.debug("Checking permission for " + groupId + " "
280: + name + " " + primKey + " " + actionId
281: + " takes " + stopWatch.getTime() + " ms");
282: }
283: }
284:
285: return value.booleanValue();
286: }
287:
288: public boolean hasUserPermission(long groupId, String name,
289: String primKey, String actionId, boolean checkAdmin) {
290:
291: try {
292: return hasUserPermissionImpl(groupId, name, primKey,
293: actionId, checkAdmin);
294: } catch (Exception e) {
295: _log.error(e, e);
296:
297: return false;
298: }
299: }
300:
301: public boolean isOmniadmin() {
302: if (omniadmin == null) {
303: omniadmin = Boolean.valueOf(OmniadminUtil
304: .isOmniadmin(getUserId()));
305: }
306:
307: return omniadmin.booleanValue();
308: }
309:
310: public boolean isCompanyAdmin(long companyId) {
311: try {
312: return isCompanyAdminImpl(companyId);
313: } catch (Exception e) {
314: _log.error(e, e);
315:
316: return false;
317: }
318: }
319:
320: public boolean isCommunityAdmin(long groupId) {
321: try {
322: return isCommunityAdminImpl(groupId);
323: } catch (Exception e) {
324: _log.error(e, e);
325:
326: return false;
327: }
328: }
329:
330: public boolean isCommunityOwner(long groupId) {
331: try {
332: return isCommunityOwnerImpl(groupId);
333: } catch (Exception e) {
334: _log.error(e, e);
335:
336: return false;
337: }
338: }
339:
340: protected PermissionCheckerBag getBag(long groupId) {
341: return (PermissionCheckerBag) bags.get(new Long(groupId));
342: }
343:
344: protected long[] getResourceIds(long companyId, long groupId,
345: String name, String primKey, String actionId)
346: throws Exception {
347:
348: // Individual
349:
350: long[] resourceIds = new long[4];
351:
352: try {
353: Resource resource = ResourceLocalServiceUtil.getResource(
354: companyId, name, ResourceImpl.SCOPE_INDIVIDUAL,
355: primKey);
356:
357: resourceIds[0] = resource.getResourceId();
358: } catch (NoSuchResourceException nsre) {
359: if (_log.isWarnEnabled()) {
360: _log.warn("Resource " + companyId + " " + name + " "
361: + ResourceImpl.SCOPE_INDIVIDUAL + " " + primKey
362: + " does not exist");
363: }
364: }
365:
366: // Group
367:
368: try {
369: if (groupId > 0) {
370: Resource resource = ResourceLocalServiceUtil
371: .getResource(companyId, name,
372: ResourceImpl.SCOPE_GROUP, String
373: .valueOf(groupId));
374:
375: resourceIds[1] = resource.getResourceId();
376: }
377: } catch (NoSuchResourceException nsre) {
378: if (_log.isWarnEnabled()) {
379: _log.warn("Resource " + companyId + " " + name + " "
380: + ResourceImpl.SCOPE_GROUP + " " + groupId
381: + " does not exist");
382: }
383: }
384:
385: // Group template
386:
387: try {
388: if (groupId > 0) {
389: Resource resource = ResourceLocalServiceUtil
390: .getResource(
391: companyId,
392: name,
393: ResourceImpl.SCOPE_GROUP_TEMPLATE,
394: String
395: .valueOf(GroupImpl.DEFAULT_PARENT_GROUP_ID));
396:
397: resourceIds[2] = resource.getResourceId();
398: }
399: } catch (NoSuchResourceException nsre) {
400: if (_log.isWarnEnabled()) {
401: _log.warn("Resource " + companyId + " " + name + " "
402: + ResourceImpl.SCOPE_GROUP_TEMPLATE + " "
403: + GroupImpl.DEFAULT_PARENT_GROUP_ID
404: + " does not exist");
405: }
406: }
407:
408: // Company
409:
410: try {
411: Resource resource = ResourceLocalServiceUtil.getResource(
412: companyId, name, ResourceImpl.SCOPE_COMPANY, String
413: .valueOf(companyId));
414:
415: resourceIds[3] = resource.getResourceId();
416: } catch (NoSuchResourceException nsre) {
417: if (_log.isWarnEnabled()) {
418: _log.warn("Resource " + companyId + " " + name + " "
419: + ResourceImpl.SCOPE_COMPANY + " " + companyId
420: + " does not exist");
421: }
422: }
423:
424: return resourceIds;
425: }
426:
427: protected List getUserOrgs(long userId) throws Exception {
428: List userOrgs = OrganizationLocalServiceUtil
429: .getUserOrganizations(userId);
430:
431: if (userOrgs.size() == 0) {
432: return userOrgs;
433: }
434:
435: List organizations = new UniqueList();
436:
437: Iterator itr = userOrgs.iterator();
438:
439: while (itr.hasNext()) {
440: Organization organization = (Organization) itr.next();
441:
442: if (!organizations.contains(organization)) {
443: organizations.add(organization);
444:
445: List ancestorOrganizations = OrganizationLocalServiceUtil
446: .getParentOrganizations(organization
447: .getOrganizationId());
448:
449: organizations.addAll(ancestorOrganizations);
450: }
451: }
452:
453: return organizations;
454: }
455:
456: protected boolean hasGuestPermission(String name, String primKey,
457: String actionId) throws Exception {
458:
459: if (name.indexOf(StringPool.PERIOD) != -1) {
460:
461: // Check unsupported model actions
462:
463: List actions = ResourceActionsUtil
464: .getModelResourceGuestUnsupportedActions(name);
465:
466: if (actions.contains(actionId)) {
467: return false;
468: }
469: } else {
470:
471: // Check unsupported portlet actions
472:
473: List actions = ResourceActionsUtil
474: .getPortletResourceGuestUnsupportedActions(name);
475:
476: if (actions.contains(actionId)) {
477: return false;
478: }
479: }
480:
481: long companyId = user.getCompanyId();
482:
483: long[] resourceIds = getResourceIds(companyId, 0, name,
484: primKey, actionId);
485:
486: PermissionCheckerBag bag = getBag(GUEST_GROUP_BAG_ID);
487:
488: if (bag == null) {
489: Group guestGroup = GroupLocalServiceUtil.getGroup(
490: companyId, GroupImpl.GUEST);
491:
492: List roles = RoleLocalServiceUtil.getGroupRoles(guestGroup
493: .getGroupId());
494:
495: bag = new PermissionCheckerBagImpl(defaultUserId,
496: new ArrayList(), new ArrayList(), new ArrayList(),
497: new ArrayList(), new ArrayList(), roles);
498:
499: putBag(GUEST_GROUP_BAG_ID, bag);
500: }
501:
502: try {
503: return PermissionLocalServiceUtil.hasUserPermissions(
504: defaultUserId, 0, actionId, resourceIds, bag);
505: } catch (Exception e) {
506: return false;
507: }
508: }
509:
510: protected boolean hasPermissionImpl(long groupId, String name,
511: String primKey, String actionId) {
512:
513: try {
514: if (!signedIn) {
515: return hasGuestPermission(name, primKey, actionId);
516: } else {
517: boolean value = false;
518:
519: if (checkGuest) {
520: value = hasGuestPermission(name, primKey, actionId);
521: }
522:
523: if (!value) {
524: value = hasUserPermission(groupId, name, primKey,
525: actionId, true);
526: }
527:
528: return value;
529: }
530: } catch (Exception e) {
531: _log.error(e, e);
532:
533: return false;
534: }
535: }
536:
537: public boolean hasUserPermissionImpl(long groupId, String name,
538: String primKey, String actionId, boolean checkAdmin)
539: throws Exception {
540:
541: StopWatch stopWatch = null;
542:
543: if (_log.isDebugEnabled()) {
544: stopWatch = new StopWatch();
545:
546: stopWatch.start();
547: }
548:
549: long companyId = user.getCompanyId();
550:
551: boolean hasLayoutManagerPermission = true;
552:
553: // Check if the layout manager has permission to do this action for the
554: // current portlet
555:
556: if ((Validator.isNotNull(name))
557: && (Validator.isNotNull(primKey))
558: && (primKey.indexOf(PortletImpl.LAYOUT_SEPARATOR) != -1)) {
559:
560: hasLayoutManagerPermission = PortletPermissionUtil
561: .hasLayoutManagerPermission(name, actionId);
562: }
563:
564: if (checkAdmin
565: && (isCompanyAdminImpl(companyId) || (isCommunityAdminImpl(groupId) && hasLayoutManagerPermission))) {
566:
567: return true;
568: }
569:
570: logHasUserPermission(groupId, name, primKey, actionId,
571: stopWatch, 1);
572:
573: long[] resourceIds = getResourceIds(companyId, groupId, name,
574: primKey, actionId);
575:
576: logHasUserPermission(groupId, name, primKey, actionId,
577: stopWatch, 2);
578:
579: // Check if user has access to perform the action on the given
580: // resource scopes. The resources are scoped to check first for an
581: // individual class, then for the group that the class may belong
582: // to, and then for the company that the class belongs to.
583:
584: PermissionCheckerBag bag = getBag(groupId);
585:
586: boolean value = PermissionLocalServiceUtil.hasUserPermissions(
587: user.getUserId(), groupId, actionId, resourceIds, bag);
588:
589: logHasUserPermission(groupId, name, primKey, actionId,
590: stopWatch, 3);
591:
592: return value;
593: }
594:
595: protected boolean isCompanyAdminImpl(long companyId)
596: throws Exception {
597: if (isOmniadmin()) {
598: return true;
599: }
600:
601: String key = String.valueOf(companyId);
602:
603: Boolean value = (Boolean) companyAdmins.get(key);
604:
605: if (value == null) {
606: boolean hasAdminRole = RoleLocalServiceUtil.hasUserRole(
607: user.getUserId(), companyId,
608: RoleImpl.ADMINISTRATOR, true);
609:
610: value = Boolean.valueOf(hasAdminRole);
611:
612: companyAdmins.put(key, value);
613: }
614:
615: return value.booleanValue();
616: }
617:
618: protected boolean isCommunityAdminImpl(long groupId)
619: throws Exception {
620: if (isOmniadmin()) {
621: return true;
622: }
623:
624: if (groupId <= 0) {
625: return false;
626: }
627:
628: Group group = GroupLocalServiceUtil.getGroup(groupId);
629:
630: if (isCompanyAdmin(group.getCompanyId())) {
631: return true;
632: }
633:
634: PermissionCheckerBag bag = getBag(groupId);
635:
636: if (bag == null) {
637: _log.error("Bag should never be null");
638: }
639:
640: if (bag.isCommunityAdmin(this , group)) {
641: return true;
642: } else {
643: return false;
644: }
645: }
646:
647: protected boolean isCommunityOwnerImpl(long groupId)
648: throws Exception {
649: if (isOmniadmin()) {
650: return true;
651: }
652:
653: if (groupId <= 0) {
654: return false;
655: }
656:
657: Group group = GroupLocalServiceUtil.getGroup(groupId);
658:
659: if (isCompanyAdmin(group.getCompanyId())) {
660: return true;
661: }
662:
663: PermissionCheckerBag bag = getBag(groupId);
664:
665: if (bag == null) {
666: _log.error("Bag should never be null");
667: }
668:
669: if (bag.isCommunityOwner(this , group)) {
670: return true;
671: } else {
672: return false;
673: }
674: }
675:
676: protected void logHasUserPermission(long groupId, String name,
677: String primKey, String actionId, StopWatch stopWatch,
678: int block) {
679:
680: if (!_log.isDebugEnabled()) {
681: return;
682: }
683:
684: _log.debug("Checking user permission block " + block + " for "
685: + groupId + " " + name + " " + primKey + " " + actionId
686: + " takes " + stopWatch.getTime() + " ms");
687: }
688:
689: protected void putBag(long groupId, PermissionCheckerBag bag) {
690: bags.put(new Long(groupId), bag);
691: }
692:
693: protected static final int GUEST_GROUP_BAG_ID = -101;
694:
695: protected static final String RESULTS_SEPARATOR = "_RESULTS_SEPARATOR_";
696:
697: protected User user;
698: protected long defaultUserId;
699: protected boolean signedIn;
700: protected boolean checkGuest;
701: protected Boolean omniadmin;
702: protected Map companyAdmins = new HashMap();
703: protected Map bags = CollectionFactory.getHashMap();
704:
705: private static Log _log = LogFactory
706: .getLog(PermissionCheckerImpl.class);
707:
708: }
|