001
014
015 package com.liferay.portal.security.permission;
016
017 import com.liferay.portal.NoSuchResourceException;
018 import com.liferay.portal.kernel.log.Log;
019 import com.liferay.portal.kernel.log.LogFactoryUtil;
020 import com.liferay.portal.kernel.util.ArrayUtil;
021 import com.liferay.portal.kernel.util.SetUtil;
022 import com.liferay.portal.kernel.util.StringPool;
023 import com.liferay.portal.kernel.util.Validator;
024 import com.liferay.portal.model.Group;
025 import com.liferay.portal.model.GroupConstants;
026 import com.liferay.portal.model.Layout;
027 import com.liferay.portal.model.Organization;
028 import com.liferay.portal.model.Permission;
029 import com.liferay.portal.model.PortletConstants;
030 import com.liferay.portal.model.Resource;
031 import com.liferay.portal.model.ResourceConstants;
032 import com.liferay.portal.model.Role;
033 import com.liferay.portal.model.RoleConstants;
034 import com.liferay.portal.model.Team;
035 import com.liferay.portal.model.UserGroup;
036 import com.liferay.portal.security.permission.comparator.PermissionActionIdComparator;
037 import com.liferay.portal.service.GroupLocalServiceUtil;
038 import com.liferay.portal.service.LayoutLocalServiceUtil;
039 import com.liferay.portal.service.OrganizationLocalServiceUtil;
040 import com.liferay.portal.service.PermissionLocalServiceUtil;
041 import com.liferay.portal.service.ResourceLocalServiceUtil;
042 import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
043 import com.liferay.portal.service.RoleLocalServiceUtil;
044 import com.liferay.portal.service.TeamLocalServiceUtil;
045 import com.liferay.portal.service.UserGroupLocalServiceUtil;
046 import com.liferay.portal.service.permission.PortletPermissionUtil;
047 import com.liferay.portal.util.PropsValues;
048 import com.liferay.util.UniqueList;
049
050 import java.util.ArrayList;
051 import java.util.Collections;
052 import java.util.HashMap;
053 import java.util.List;
054 import java.util.Map;
055 import java.util.Set;
056
057 import org.apache.commons.lang.time.StopWatch;
058
059
064 public class AdvancedPermissionChecker extends BasePermissionChecker {
065
066 public long[] getRoleIds(long userId, long groupId) {
067 PermissionCheckerBag bag = null;
068
069 try {
070 bag = getUserBag(userId, groupId);
071 }
072 catch (Exception e) {
073 }
074
075 if (bag != null) {
076 if (checkGuest) {
077 Set<Long> roleIds = SetUtil.fromArray(bag.getRoleIds());
078
079 try {
080 PermissionCheckerBag guestBag = getGuestUserBag();
081
082 if (guestBag != null) {
083 for (long roleId : guestBag.getRoleIds()) {
084 roleIds.add(roleId);
085 }
086 }
087 }
088 catch (Exception e) {
089 }
090
091 return ArrayUtil.toArray(
092 roleIds.toArray(new Long[roleIds.size()]));
093 }
094 else {
095 return bag.getRoleIds();
096 }
097 }
098
099 return PermissionChecker.DEFAULT_ROLE_IDS;
100 }
101
102 public PermissionCheckerBag getGuestUserBag() throws Exception {
103 Group guestGroup = GroupLocalServiceUtil.getGroup(
104 getCompanyId(), GroupConstants.GUEST);
105
106 PermissionCheckerBag bag = PermissionCacheUtil.getBag(
107 defaultUserId, guestGroup.getGroupId());
108
109 if (bag == null) {
110 try {
111 List<Group> groups = new ArrayList<Group>();
112
113 groups.add(guestGroup);
114
115 List<Role> roles = RoleLocalServiceUtil.getUserRelatedRoles(
116 defaultUserId, groups);
117
118 bag = new PermissionCheckerBagImpl(
119 defaultUserId, new ArrayList<Group>(),
120 new ArrayList<Organization>(), new ArrayList<Group>(),
121 new ArrayList<Group>(), new ArrayList<Group>(), roles);
122 }
123 finally {
124 if (bag == null) {
125 bag = new PermissionCheckerBagImpl(
126 defaultUserId, new ArrayList<Group>(),
127 new ArrayList<Organization>(), new ArrayList<Group>(),
128 new ArrayList<Group>(), new ArrayList<Group>(),
129 new ArrayList<Role>());
130 }
131
132 PermissionCacheUtil.putBag(
133 defaultUserId, guestGroup.getGroupId(), bag);
134 }
135 }
136
137 return bag;
138 }
139
140 public PermissionCheckerBag getUserBag(long userId, long groupId)
141 throws Exception {
142
143 PermissionCheckerBag bag = PermissionCacheUtil.getBag(userId, groupId);
144
145 if (bag != null) {
146 return bag;
147 }
148
149 try {
150
151 Group group = null;
152
153 if (groupId > 0) {
154 group = GroupLocalServiceUtil.getGroup(groupId);
155 }
156
157
158
159
160
161
162
163 List<Group> userGroups = new ArrayList<Group>();
164
165
166 if ((group != null) && group.isCommunity() &&
167 GroupLocalServiceUtil.hasUserGroup(userId, groupId)) {
168
169 userGroups.add(group);
170 }
171
172 List<Organization> userOrgs = getUserOrgs(userId);
173
174 List<Group> userOrgGroups =
175 GroupLocalServiceUtil.getOrganizationsGroups(userOrgs);
176
177 List<UserGroup> userUserGroups =
178 UserGroupLocalServiceUtil.getUserUserGroups(userId);
179
180 List<Group> userUserGroupGroups =
181 GroupLocalServiceUtil.getUserGroupsGroups(userUserGroups);
182
183 List<Group> groups = new ArrayList<Group>(
184 userGroups.size() + userOrgGroups.size() +
185 userUserGroupGroups.size());
186
187 groups.addAll(userGroups);
188 groups.addAll(userOrgGroups);
189 groups.addAll(userUserGroupGroups);
190
191 List<Role> roles = new UniqueList<Role>();
192
193 if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 3) ||
194 (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 4) ||
195 (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) ||
196 (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6)) {
197
198 if (groups.size() > 0) {
199 List<Role> userRelatedRoles=
200 RoleLocalServiceUtil.getUserRelatedRoles(
201 userId, groups);
202
203 roles.addAll(userRelatedRoles);
204 }
205 else {
206 roles.addAll(RoleLocalServiceUtil.getUserRoles(userId));
207 }
208
209 List<Role> userGroupRoles =
210 RoleLocalServiceUtil.getUserGroupRoles(userId, groupId);
211
212 roles.addAll(userGroupRoles);
213
214 List<Role> userGroupGroupRoles =
215 RoleLocalServiceUtil.getUserGroupGroupRoles(
216 userId, groupId);
217
218 roles.addAll(userGroupGroupRoles);
219
220 if ((group != null) &&
221 ((group.isCommunity() && userGroups.contains(group)) ||
222 (group.isOrganization() &&
223 userOrgGroups.contains(group)))) {
224
225 addRequiredMemberRole(group, roles);
226 addTeamRoles(userId, group, roles);
227 }
228 }
229 else {
230 roles = new ArrayList<Role>();
231 }
232
233 bag = new PermissionCheckerBagImpl(
234 userId, userGroups, userOrgs, userOrgGroups,
235 userUserGroupGroups, groups, roles);
236
237 return bag;
238 }
239 finally {
240 if (bag == null) {
241 bag = new PermissionCheckerBagImpl(
242 userId, new ArrayList<Group>(),
243 new ArrayList<Organization>(), new ArrayList<Group>(),
244 new ArrayList<Group>(), new ArrayList<Group>(),
245 new ArrayList<Role>());
246 }
247
248 PermissionCacheUtil.putBag(userId, groupId, bag);
249 }
250 }
251
252 public boolean hasOwnerPermission(
253 long companyId, String name, String primKey, long ownerId,
254 String actionId) {
255
256 if (ownerId != getUserId()) {
257 return false;
258 }
259
260 if (ownerId == defaultUserId) {
261 if (actionId.equals(ActionKeys.VIEW)) {
262 return true;
263 }
264 else {
265 return false;
266 }
267 }
268
269 try {
270 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
271 return ResourcePermissionLocalServiceUtil.hasResourcePermission(
272 companyId, name, ResourceConstants.SCOPE_INDIVIDUAL,
273 primKey, getOwnerRoleId(), actionId);
274 }
275 else {
276 ResourceActionsUtil.checkAction(name, actionId);
277
278 Resource resource = ResourceLocalServiceUtil.getResource(
279 companyId, name, ResourceConstants.SCOPE_INDIVIDUAL,
280 primKey);
281
282 List<Permission> permissions =
283 PermissionLocalServiceUtil.getRolePermissions(
284 getOwnerRoleId(), resource.getResourceId());
285
286 int pos = Collections.binarySearch(
287 permissions, actionId, new PermissionActionIdComparator());
288
289 if (pos >= 0) {
290 return true;
291 }
292 }
293 }
294 catch (Exception e) {
295 if (_log.isDebugEnabled()) {
296 _log.debug(e, e);
297 }
298 }
299
300 return false;
301 }
302
303 public boolean hasPermission(
304 long groupId, String name, String primKey, String actionId) {
305
306 StopWatch stopWatch = null;
307
308 if (_log.isDebugEnabled()) {
309 stopWatch = new StopWatch();
310
311 stopWatch.start();
312 }
313
314 Group group = null;
315
316
317
318
319
320 try {
321 if (groupId > 0) {
322 group = GroupLocalServiceUtil.getGroup(groupId);
323
324 if (group.isLayout()) {
325 Layout layout = LayoutLocalServiceUtil.getLayout(
326 group.getClassPK());
327
328 groupId = layout.getGroupId();
329
330 group = GroupLocalServiceUtil.getGroup(groupId);
331 }
332
333 if (group.isStagingGroup()) {
334 if (primKey.equals(String.valueOf(groupId))) {
335 primKey = String.valueOf(group.getLiveGroupId());
336 }
337
338 groupId = group.getLiveGroupId();
339 group = group.getLiveGroup();
340 }
341 }
342 }
343 catch (Exception e) {
344 _log.error(e, e);
345 }
346
347 Boolean value = PermissionCacheUtil.getPermission(
348 user.getUserId(), groupId, name, primKey, actionId);
349
350 if (value == null) {
351 try {
352 value = Boolean.valueOf(
353 hasPermissionImpl(groupId, name, primKey, actionId));
354
355 if (_log.isDebugEnabled()) {
356 _log.debug(
357 "Checking permission for " + groupId + " " + name +
358 " " + primKey + " " + actionId + " takes " +
359 stopWatch.getTime() + " ms");
360 }
361 }
362 finally {
363 if (value == null) {
364 value = Boolean.FALSE;
365 }
366
367 PermissionCacheUtil.putPermission(
368 user.getUserId(), groupId, name, primKey, actionId, value);
369 }
370 }
371
372 return value.booleanValue();
373 }
374
375 public boolean hasUserPermission(
376 long groupId, String name, String primKey, String actionId,
377 boolean checkAdmin) {
378
379 try {
380 return hasUserPermissionImpl(
381 groupId, name, primKey, actionId, checkAdmin);
382 }
383 catch (Exception e) {
384 _log.error(e, e);
385
386 return false;
387 }
388 }
389
390 public boolean isCommunityAdmin(long groupId) {
391 try {
392 return isCommunityAdminImpl(groupId);
393 }
394 catch (Exception e) {
395 _log.error(e, e);
396
397 return false;
398 }
399 }
400
401 public boolean isCommunityOwner(long groupId) {
402 try {
403 return isCommunityOwnerImpl(groupId);
404 }
405 catch (Exception e) {
406 _log.error(e, e);
407
408 return false;
409 }
410 }
411
412 public boolean isCompanyAdmin() {
413 try {
414 return isCompanyAdminImpl();
415 }
416 catch (Exception e) {
417 _log.error(e, e);
418
419 return false;
420 }
421 }
422
423 public boolean isCompanyAdmin(long companyId) {
424 try {
425 return isCompanyAdminImpl(companyId);
426 }
427 catch (Exception e) {
428 _log.error(e, e);
429
430 return false;
431 }
432 }
433
434 protected void addRequiredMemberRole(Group group, List<Role> roles)
435 throws Exception {
436
437 if (group.isCommunity()) {
438 Role communityMemberRole = RoleLocalServiceUtil.getRole(
439 group.getCompanyId(), RoleConstants.COMMUNITY_MEMBER);
440
441 roles.add(communityMemberRole);
442 }
443 else if (group.isOrganization()) {
444 Role organizationMemberRole = RoleLocalServiceUtil.getRole(
445 group.getCompanyId(), RoleConstants.ORGANIZATION_MEMBER);
446
447 roles.add(organizationMemberRole);
448 }
449 }
450
451 protected void addTeamRoles(long userId, Group group, List<Role> roles)
452 throws Exception {
453
454 if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) ||
455 (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6)) {
456
457 List<Team> teams = TeamLocalServiceUtil.getUserTeams(
458 userId, group.getGroupId());
459
460 for (Team team : teams) {
461 Role role = RoleLocalServiceUtil.getTeamRole(
462 team.getCompanyId(), team.getTeamId());
463
464 roles.add(role);
465 }
466 }
467 }
468
469 protected List<Resource> getResources(
470 long companyId, long groupId, String name, String primKey,
471 String actionId)
472 throws Exception {
473
474
475
476 List<Resource> resources = new ArrayList<Resource>(4);
477
478 try {
479 Resource resource = ResourceLocalServiceUtil.getResource(
480 companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
481
482 resources.add(resource);
483 }
484 catch (NoSuchResourceException nsre) {
485 if (_log.isWarnEnabled()) {
486 _log.warn(
487 "Resource " + companyId + " " + name + " " +
488 ResourceConstants.SCOPE_INDIVIDUAL + " " + primKey +
489 " does not exist");
490 }
491 }
492
493
494
495 try {
496 if (groupId > 0) {
497 Resource resource = ResourceLocalServiceUtil.getResource(
498 companyId, name, ResourceConstants.SCOPE_GROUP,
499 String.valueOf(groupId));
500
501 resources.add(resource);
502 }
503 }
504 catch (NoSuchResourceException nsre) {
505 if (_log.isWarnEnabled()) {
506 _log.warn(
507 "Resource " + companyId + " " + name + " " +
508 ResourceConstants.SCOPE_GROUP + " " + groupId +
509 " does not exist");
510 }
511 }
512
513
514
515 try {
516 if (signedIn && (groupId > 0)) {
517 Resource resource = ResourceLocalServiceUtil.getResource(
518 companyId, name, ResourceConstants.SCOPE_GROUP_TEMPLATE,
519 String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID));
520
521 resources.add(resource);
522 }
523 }
524 catch (NoSuchResourceException nsre) {
525 if (_log.isWarnEnabled()) {
526 _log.warn(
527 "Resource " + companyId + " " + name + " " +
528 ResourceConstants.SCOPE_GROUP_TEMPLATE + " " +
529 GroupConstants.DEFAULT_PARENT_GROUP_ID +
530 " does not exist");
531 }
532 }
533
534
535
536 try {
537 Resource resource = ResourceLocalServiceUtil.getResource(
538 companyId, name, ResourceConstants.SCOPE_COMPANY,
539 String.valueOf(companyId));
540
541 resources.add(resource);
542 }
543 catch (NoSuchResourceException nsre) {
544 if (_log.isWarnEnabled()) {
545 _log.warn(
546 "Resource " + companyId + " " + name + " " +
547 ResourceConstants.SCOPE_COMPANY + " " + companyId +
548 " does not exist");
549 }
550 }
551
552 return resources;
553 }
554
555 protected List<Organization> getUserOrgs(long userId) throws Exception {
556 List<Organization> userOrgs =
557 OrganizationLocalServiceUtil.getUserOrganizations(userId, true);
558
559 if (userOrgs.size() == 0) {
560 return userOrgs;
561 }
562
563 List<Organization> organizations = new UniqueList<Organization>();
564
565 for (Organization organization : userOrgs) {
566 if (!organizations.contains(organization)) {
567 organizations.add(organization);
568
569 List<Organization> ancestorOrganizations =
570 OrganizationLocalServiceUtil.getParentOrganizations(
571 organization.getOrganizationId());
572
573 organizations.addAll(ancestorOrganizations);
574 }
575 }
576
577 return organizations;
578 }
579
580 protected boolean hasGuestPermission(
581 long groupId, String name, String primKey, String actionId)
582 throws Exception {
583
584 ResourceActionsUtil.checkAction(name, actionId);
585
586 if (name.indexOf(StringPool.PERIOD) != -1) {
587
588
589
590 List<String> actions = ResourceActionsUtil.
591 getModelResourceGuestUnsupportedActions(name);
592
593 if (actions.contains(actionId)) {
594 return false;
595 }
596 }
597 else {
598
599
600
601 List<String> actions = ResourceActionsUtil.
602 getPortletResourceGuestUnsupportedActions(name);
603
604 if (actions.contains(actionId)) {
605 return false;
606 }
607 }
608
609 long companyId = user.getCompanyId();
610
611 List<Resource> resources = getResources(
612 companyId, groupId, name, primKey, actionId);
613
614 PermissionCheckerBag bag = getGuestUserBag();
615
616 try {
617 return PermissionLocalServiceUtil.hasUserPermissions(
618 defaultUserId, groupId, resources, actionId, bag);
619 }
620 catch (Exception e) {
621 _log.error(e, e);
622
623 return false;
624 }
625 }
626
627 protected boolean hasPermissionImpl(
628 long groupId, String name, String primKey, String actionId) {
629
630 try {
631 if (!signedIn) {
632 return hasGuestPermission(groupId, name, primKey, actionId);
633 }
634 else {
635 boolean value = false;
636
637 if (checkGuest) {
638 value = hasGuestPermission(
639 groupId, name, primKey, actionId);
640 }
641
642 if (!value) {
643 value = hasUserPermission(
644 groupId, name, primKey, actionId, true);
645 }
646
647 return value;
648 }
649 }
650 catch (Exception e) {
651 _log.error(e, e);
652
653 return false;
654 }
655 }
656
657 protected boolean hasUserPermissionImpl(
658 long groupId, String name, String primKey, String actionId,
659 boolean checkAdmin)
660 throws Exception {
661
662 StopWatch stopWatch = null;
663
664 if (_log.isDebugEnabled()) {
665 stopWatch = new StopWatch();
666
667 stopWatch.start();
668 }
669
670 long companyId = user.getCompanyId();
671
672 boolean hasLayoutManagerPermission = true;
673
674
675
676
677 if ((Validator.isNotNull(name)) && (Validator.isNotNull(primKey)) &&
678 (primKey.indexOf(PortletConstants.LAYOUT_SEPARATOR) != -1)) {
679
680 hasLayoutManagerPermission =
681 PortletPermissionUtil.hasLayoutManagerPermission(
682 name, actionId);
683 }
684
685 if (checkAdmin &&
686 (isCompanyAdminImpl(companyId) ||
687 (isCommunityAdminImpl(groupId) &&
688 hasLayoutManagerPermission))) {
689
690 return true;
691 }
692
693 logHasUserPermission(groupId, name, primKey, actionId, stopWatch, 1);
694
695 List<Resource> resources = getResources(
696 companyId, groupId, name, primKey, actionId);
697
698 logHasUserPermission(groupId, name, primKey, actionId, stopWatch, 2);
699
700
701
702
703
704
705 PermissionCheckerBag bag = getUserBag(user.getUserId(), groupId);
706
707 boolean value = PermissionLocalServiceUtil.hasUserPermissions(
708 user.getUserId(), groupId, resources, actionId, bag);
709
710 logHasUserPermission(groupId, name, primKey, actionId, stopWatch, 3);
711
712 return value;
713 }
714
715 protected boolean isCommunityAdminImpl(long groupId) throws Exception {
716 if (!signedIn) {
717 return false;
718 }
719
720 if (isOmniadmin()) {
721 return true;
722 }
723
724 if (groupId <= 0) {
725 return false;
726 }
727
728 Group group = GroupLocalServiceUtil.getGroup(groupId);
729
730 if (isCompanyAdmin(group.getCompanyId())) {
731 return true;
732 }
733
734 PermissionCheckerBag bag = getUserBag(user.getUserId(), groupId);
735
736 if (bag == null) {
737 _log.error("Bag should never be null");
738 }
739
740 if (bag.isCommunityAdmin(this, group)) {
741 return true;
742 }
743 else {
744 return false;
745 }
746 }
747
748 protected boolean isCommunityOwnerImpl(long groupId) throws Exception {
749 if (!signedIn) {
750 return false;
751 }
752
753 if (isOmniadmin()) {
754 return true;
755 }
756
757 if (groupId <= 0) {
758 return false;
759 }
760
761 Group group = GroupLocalServiceUtil.getGroup(groupId);
762
763 if (isCompanyAdmin(group.getCompanyId())) {
764 return true;
765 }
766
767 PermissionCheckerBag bag = getUserBag(user.getUserId(), groupId);
768
769 if (bag == null) {
770 _log.error("Bag should never be null");
771 }
772
773 if (bag.isCommunityOwner(this, group)) {
774 return true;
775 }
776 else {
777 return false;
778 }
779 }
780
781 protected boolean isCompanyAdminImpl() throws Exception {
782 return isCompanyAdminImpl(user.getCompanyId());
783 }
784
785 protected boolean isCompanyAdminImpl(long companyId) throws Exception {
786 if (!signedIn) {
787 return false;
788 }
789
790 if (isOmniadmin()) {
791 return true;
792 }
793
794 Boolean value = companyAdmins.get(companyId);
795
796 if (value == null) {
797 boolean hasAdminRole = RoleLocalServiceUtil.hasUserRole(
798 user.getUserId(), companyId, RoleConstants.ADMINISTRATOR, true);
799
800 value = Boolean.valueOf(hasAdminRole);
801
802 companyAdmins.put(companyId, value);
803 }
804
805 return value.booleanValue();
806 }
807
808 protected void logHasUserPermission(
809 long groupId, String name, String primKey, String actionId,
810 StopWatch stopWatch, int block) {
811
812 if (!_log.isDebugEnabled()) {
813 return;
814 }
815
816 _log.debug(
817 "Checking user permission block " + block + " for " + groupId +
818 " " + name + " " + primKey + " " + actionId + " takes " +
819 stopWatch.getTime() + " ms");
820 }
821
822
825 protected static final String RESULTS_SEPARATOR = "_RESULTS_SEPARATOR_";
826
827 protected Map<Long, Boolean> companyAdmins = new HashMap<Long, Boolean>();
828
829 private static Log _log = LogFactoryUtil.getLog(
830 AdvancedPermissionChecker.class);
831
832 }