001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.security.permission;
016    
017    import com.liferay.portal.NoSuchResourceException;
018    import com.liferay.portal.kernel.dao.orm.QueryUtil;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.util.ArrayUtil;
023    import com.liferay.portal.kernel.util.CharPool;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.SetUtil;
026    import com.liferay.portal.kernel.util.UniqueList;
027    import com.liferay.portal.kernel.util.Validator;
028    import com.liferay.portal.model.Group;
029    import com.liferay.portal.model.GroupConstants;
030    import com.liferay.portal.model.GroupedModel;
031    import com.liferay.portal.model.Layout;
032    import com.liferay.portal.model.Organization;
033    import com.liferay.portal.model.Permission;
034    import com.liferay.portal.model.PermissionedModel;
035    import com.liferay.portal.model.PortletConstants;
036    import com.liferay.portal.model.Resource;
037    import com.liferay.portal.model.ResourceBlockConstants;
038    import com.liferay.portal.model.ResourceConstants;
039    import com.liferay.portal.model.Role;
040    import com.liferay.portal.model.RoleConstants;
041    import com.liferay.portal.model.Team;
042    import com.liferay.portal.model.UserGroup;
043    import com.liferay.portal.security.permission.comparator.PermissionActionIdComparator;
044    import com.liferay.portal.service.GroupLocalServiceUtil;
045    import com.liferay.portal.service.LayoutLocalServiceUtil;
046    import com.liferay.portal.service.OrganizationLocalServiceUtil;
047    import com.liferay.portal.service.PermissionLocalServiceUtil;
048    import com.liferay.portal.service.ResourceBlockLocalServiceUtil;
049    import com.liferay.portal.service.ResourceLocalServiceUtil;
050    import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
051    import com.liferay.portal.service.RoleLocalServiceUtil;
052    import com.liferay.portal.service.TeamLocalServiceUtil;
053    import com.liferay.portal.service.UserGroupLocalServiceUtil;
054    import com.liferay.portal.service.permission.PortletPermissionUtil;
055    import com.liferay.portal.util.PropsValues;
056    
057    import java.util.ArrayList;
058    import java.util.Collections;
059    import java.util.HashMap;
060    import java.util.LinkedHashMap;
061    import java.util.List;
062    import java.util.Map;
063    import java.util.Set;
064    
065    import org.apache.commons.lang.time.StopWatch;
066    
067    /**
068     * @author Charles May
069     * @author Brian Wing Shun Chan
070     * @author Raymond Aug??
071     * @author Wesley Gong
072     * @author Connor McKay
073     */
074    public class AdvancedPermissionChecker extends BasePermissionChecker {
075    
076            @Override
077            public AdvancedPermissionChecker clone() {
078                    return new AdvancedPermissionChecker();
079            }
080    
081            @Override
082            public List<Long> getGuestResourceBlockIds(
083                    long companyId, long groupId, String name, String actionId) {
084    
085                    try {
086                            ResourceBlockIdsBag resourceBlockIdsBag =
087                                    getGuestResourceBlockIdsBag(companyId, groupId, name);
088    
089                            return ResourceBlockLocalServiceUtil.getResourceBlockIds(
090                                    resourceBlockIdsBag, name, actionId);
091                    }
092                    catch (Exception e) {
093                    }
094    
095                    return Collections.emptyList();
096            }
097    
098            public ResourceBlockIdsBag getGuestResourceBlockIdsBag(
099                            long companyId, long groupId, String name)
100                    throws Exception {
101    
102                    // checkGuest is irrelevant for the guest role, so it is assumed true
103    
104                    ResourceBlockIdsBag resourceBlockIdsBag =
105                            PermissionCacheUtil.getResourceBlockIdsBag(
106                                    companyId, groupId, defaultUserId, name, true);
107    
108                    if (resourceBlockIdsBag != null) {
109                            return resourceBlockIdsBag;
110                    }
111    
112                    try {
113                            PermissionCheckerBag bag = getGuestUserBag();
114    
115                            long[] roleIds = bag.getRoleIds();
116    
117                            resourceBlockIdsBag =
118                                    ResourceBlockLocalServiceUtil.getResourceBlockIdsBag(
119                                            getCompanyId(), groupId, name, roleIds);
120    
121                            PermissionCacheUtil.putResourceBlockIdsBag(
122                                    companyId, groupId, defaultUserId, name, true,
123                                    resourceBlockIdsBag);
124    
125                            return resourceBlockIdsBag;
126                    }
127                    finally {
128                            if (resourceBlockIdsBag == null) {
129                                    resourceBlockIdsBag = new ResourceBlockIdsBag();
130                            }
131    
132                            PermissionCacheUtil.putResourceBlockIdsBag(
133                                    companyId, defaultUserId, groupId, name, true,
134                                    resourceBlockIdsBag);
135                    }
136            }
137    
138            /**
139             * Returns the permission checker bag for the guest user.
140             *
141             * @return the permission checker bag for the guest user
142             * @throws Exception if an exception occurred
143             */
144            public PermissionCheckerBag getGuestUserBag() throws Exception {
145                    Group guestGroup = GroupLocalServiceUtil.getGroup(
146                            getCompanyId(), GroupConstants.GUEST);
147    
148                    PermissionCheckerBag bag = PermissionCacheUtil.getBag(
149                            defaultUserId, guestGroup.getGroupId());
150    
151                    if (bag == null) {
152                            try {
153                                    List<Group> groups = new ArrayList<Group>();
154    
155                                    groups.add(guestGroup);
156    
157                                    List<Role> roles = RoleLocalServiceUtil.getUserRelatedRoles(
158                                            defaultUserId, groups);
159    
160                                    // Only use the guest group for deriving the roles for
161                                    // unauthenticated users. Do not add the group to the permission
162                                    // bag as this implies group membership which is incorrect in
163                                    // the case of unauthenticated users.
164    
165                                    bag = new PermissionCheckerBagImpl(
166                                            defaultUserId, new ArrayList<Group>(),
167                                            new ArrayList<Organization>(), new ArrayList<Group>(),
168                                            new ArrayList<Group>(), new ArrayList<Group>(), roles);
169                            }
170                            finally {
171                                    if (bag == null) {
172                                            bag = new PermissionCheckerBagImpl(
173                                                    defaultUserId, new ArrayList<Group>(),
174                                                    new ArrayList<Organization>(), new ArrayList<Group>(),
175                                                    new ArrayList<Group>(), new ArrayList<Group>(),
176                                                    new ArrayList<Role>());
177                                    }
178    
179                                    PermissionCacheUtil.putBag(
180                                            defaultUserId, guestGroup.getGroupId(), bag);
181                            }
182                    }
183    
184                    return bag;
185            }
186    
187            @Override
188            public List<Long> getOwnerResourceBlockIds(
189                    long companyId, long groupId, String name, String actionId) {
190    
191                    try {
192                            ResourceBlockIdsBag resourceBlockIdsBag =
193                                    getOwnerResourceBlockIdsBag(companyId, groupId, name);
194    
195                            return ResourceBlockLocalServiceUtil.getResourceBlockIds(
196                                    resourceBlockIdsBag, name, actionId);
197                    }
198                    catch (Exception e) {
199                    }
200    
201                    return Collections.emptyList();
202            }
203    
204            public ResourceBlockIdsBag getOwnerResourceBlockIdsBag(
205                            long companyId, long groupId, String name)
206                    throws SystemException {
207    
208                    // checkGuest is irrelevant for the owner role, so it is assumed true
209    
210                    ResourceBlockIdsBag resourceBlockIdsBag =
211                            PermissionCacheUtil.getResourceBlockIdsBag(
212                                    companyId, groupId, ResourceBlockConstants.OWNER_USER_ID, name,
213                                    true);
214    
215                    if (resourceBlockIdsBag != null) {
216                            return resourceBlockIdsBag;
217                    }
218    
219                    try {
220                            long[] roleIds = {getOwnerRoleId()};
221    
222                            resourceBlockIdsBag =
223                                    ResourceBlockLocalServiceUtil.getResourceBlockIdsBag(
224                                            getCompanyId(), groupId, name, roleIds);
225    
226                            PermissionCacheUtil.putResourceBlockIdsBag(
227                                    companyId, groupId, ResourceBlockConstants.OWNER_USER_ID, name,
228                                    true, resourceBlockIdsBag);
229    
230                            return resourceBlockIdsBag;
231                    }
232                    finally {
233                            if (resourceBlockIdsBag == null) {
234                                    resourceBlockIdsBag = new ResourceBlockIdsBag();
235                            }
236    
237                            PermissionCacheUtil.putResourceBlockIdsBag(
238                                    companyId, ResourceBlockConstants.OWNER_USER_ID, groupId, name,
239                                    true, resourceBlockIdsBag);
240                    }
241            }
242    
243            @Override
244            public List<Long> getResourceBlockIds(
245                    long companyId, long groupId, long userId, String name,
246                    String actionId) {
247    
248                    try {
249                            ResourceBlockIdsBag resourceBlockIdsBag = getResourceBlockIdsBag(
250                                    companyId, groupId, userId, name);
251    
252                            return ResourceBlockLocalServiceUtil.getResourceBlockIds(
253                                    resourceBlockIdsBag, name, actionId);
254                    }
255                    catch (Exception e) {
256                    }
257    
258                    return Collections.emptyList();
259            }
260    
261            public ResourceBlockIdsBag getResourceBlockIdsBag(
262                            long companyId, long groupId, long userId, String name)
263                    throws Exception {
264    
265                    ResourceBlockIdsBag resourceBlockIdsBag =
266                            PermissionCacheUtil.getResourceBlockIdsBag(
267                                    companyId, groupId, userId, name, checkGuest);
268    
269                    if (resourceBlockIdsBag != null) {
270                            return resourceBlockIdsBag;
271                    }
272    
273                    try {
274                            long[] roleIds = getRoleIds(userId, groupId);
275    
276                            resourceBlockIdsBag =
277                                    ResourceBlockLocalServiceUtil.getResourceBlockIdsBag(
278                                            getCompanyId(), groupId, name, roleIds);
279    
280                            PermissionCacheUtil.putResourceBlockIdsBag(
281                                    companyId, groupId, userId, name, checkGuest,
282                                    resourceBlockIdsBag);
283    
284                            return resourceBlockIdsBag;
285                    }
286                    finally {
287                            if (resourceBlockIdsBag == null) {
288                                    resourceBlockIdsBag = new ResourceBlockIdsBag();
289                            }
290    
291                            PermissionCacheUtil.putResourceBlockIdsBag(
292                                    companyId, userId, groupId, name, checkGuest,
293                                    resourceBlockIdsBag);
294                    }
295            }
296    
297            @Override
298            public long[] getRoleIds(long userId, long groupId) {
299                    PermissionCheckerBag bag = null;
300    
301                    try {
302                            bag = getUserBag(userId, groupId);
303                    }
304                    catch (Exception e) {
305                    }
306    
307                    if (bag == null) {
308                            return PermissionChecker.DEFAULT_ROLE_IDS;
309                    }
310    
311                    if (checkGuest) {
312                            Set<Long> roleIds = SetUtil.fromArray(bag.getRoleIds());
313    
314                            try {
315                                    PermissionCheckerBag guestBag = getGuestUserBag();
316    
317                                    if (guestBag != null) {
318                                            for (long roleId : guestBag.getRoleIds()) {
319                                                    roleIds.add(roleId);
320                                            }
321                                    }
322                            }
323                            catch (Exception e) {
324                            }
325    
326                            return ArrayUtil.toArray(roleIds.toArray(new Long[roleIds.size()]));
327                    }
328                    else {
329                            return bag.getRoleIds();
330                    }
331            }
332    
333            /**
334             * Returns the permission checker bag for the user and group. Users can have
335             * different roles and permissions in different groups.
336             *
337             * @param  userId the primary key of the user
338             * @param  groupId the primary key of the group
339             * @return the permission checker bag for the user and group
340             * @throws Exception if a user or group with the primary key could not be
341             *         found
342             */
343            public PermissionCheckerBag getUserBag(long userId, long groupId)
344                    throws Exception {
345    
346                    PermissionCheckerBag bag = PermissionCacheUtil.getBag(userId, groupId);
347    
348                    if (bag != null) {
349                            return bag;
350                    }
351    
352                    try {
353                            Group group = null;
354    
355                            long parentGroupId = 0;
356    
357                            if (groupId > 0) {
358                                    group = GroupLocalServiceUtil.getGroup(groupId);
359    
360                                    if (group.isLayout()) {
361                                            parentGroupId = group.getParentGroupId();
362    
363                                            if (parentGroupId > 0) {
364                                                    group = GroupLocalServiceUtil.getGroup(parentGroupId);
365                                            }
366                                    }
367                            }
368    
369                            List<Group> userGroups = GroupLocalServiceUtil.getUserGroups(
370                                    userId, true);
371    
372                            List<Organization> userOrgs = getUserOrgs(userId);
373    
374                            List<Group> userOrgGroups =
375                                    GroupLocalServiceUtil.getOrganizationsGroups(userOrgs);
376    
377                            List<UserGroup> userUserGroups =
378                                    UserGroupLocalServiceUtil.getUserUserGroups(userId);
379    
380                            List<Group> userUserGroupGroups =
381                                    GroupLocalServiceUtil.getUserGroupsGroups(userUserGroups);
382    
383                            List<Group> groups = new ArrayList<Group>(
384                                    userGroups.size() + userOrgGroups.size() +
385                                            userUserGroupGroups.size());
386    
387                            groups.addAll(userGroups);
388                            groups.addAll(userOrgGroups);
389                            groups.addAll(userUserGroupGroups);
390    
391                            List<Role> roles = new UniqueList<Role>();
392    
393                            if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 3) ||
394                                    (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 4) ||
395                                    (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) ||
396                                    (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6)) {
397    
398                                    if (groups.size() > 0) {
399                                            List<Role> userRelatedRoles=
400                                                    RoleLocalServiceUtil.getUserRelatedRoles(
401                                                            userId, groups);
402    
403                                            roles.addAll(userRelatedRoles);
404                                    }
405                                    else {
406                                            roles.addAll(RoleLocalServiceUtil.getUserRoles(userId));
407                                    }
408    
409                                    List<Role> userGroupRoles =
410                                            RoleLocalServiceUtil.getUserGroupRoles(userId, groupId);
411    
412                                    roles.addAll(userGroupRoles);
413    
414                                    if (parentGroupId > 0) {
415                                            userGroupRoles = RoleLocalServiceUtil.getUserGroupRoles(
416                                                    userId, parentGroupId);
417    
418                                            roles.addAll(userGroupRoles);
419                                    }
420    
421                                    List<Role> userGroupGroupRoles =
422                                            RoleLocalServiceUtil.getUserGroupGroupRoles(
423                                                    userId, groupId);
424    
425                                    roles.addAll(userGroupGroupRoles);
426    
427                                    if (parentGroupId > 0) {
428                                            userGroupGroupRoles =
429                                                    RoleLocalServiceUtil.getUserGroupGroupRoles(
430                                                            userId, parentGroupId);
431    
432                                            roles.addAll(userGroupGroupRoles);
433                                    }
434    
435                                    if (group != null) {
436                                            if (group.isOrganization() &&
437                                                    userOrgGroups.contains(group)) {
438    
439                                                    Role organizationUserRole =
440                                                            RoleLocalServiceUtil.getRole(
441                                                                    group.getCompanyId(),
442                                                                    RoleConstants.ORGANIZATION_USER);
443    
444                                                    roles.add(organizationUserRole);
445                                            }
446    
447                                            if ((group.isSite() &&
448                                                     (userGroups.contains(group) ||
449                                                      userOrgGroups.contains(group))) ||
450                                                    group.isUserPersonalSite()) {
451    
452                                                    Role siteMemberRole = RoleLocalServiceUtil.getRole(
453                                                            group.getCompanyId(), RoleConstants.SITE_MEMBER);
454    
455                                                    roles.add(siteMemberRole);
456                                            }
457    
458                                            if ((group.isOrganization() &&
459                                                     userOrgGroups.contains(group)) ||
460                                                    (group.isSite() && userGroups.contains(group))) {
461    
462                                                    addTeamRoles(userId, group, roles);
463                                            }
464                                    }
465                            }
466                            else {
467                                    roles = new ArrayList<Role>();
468                            }
469    
470                            bag = new PermissionCheckerBagImpl(
471                                    userId, userGroups, userOrgs, userOrgGroups,
472                                    userUserGroupGroups, groups, roles);
473    
474                            return bag;
475                    }
476                    finally {
477                            if (bag == null) {
478                                    bag = new PermissionCheckerBagImpl(
479                                            userId, new ArrayList<Group>(),
480                                            new ArrayList<Organization>(), new ArrayList<Group>(),
481                                            new ArrayList<Group>(), new ArrayList<Group>(),
482                                            new ArrayList<Role>());
483                            }
484    
485                            PermissionCacheUtil.putBag(userId, groupId, bag);
486                    }
487            }
488    
489            @Override
490            public boolean hasOwnerPermission(
491                    long companyId, String name, String primKey, long ownerId,
492                    String actionId) {
493    
494                    if (ownerId != getUserId()) {
495                            return false;
496                    }
497    
498                    if (ownerId == defaultUserId) {
499                            if (actionId.equals(ActionKeys.VIEW)) {
500                                    return true;
501                            }
502                            else {
503                                    return false;
504                            }
505                    }
506    
507                    try {
508                            if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
509                                    if (ResourceBlockLocalServiceUtil.isSupported(name)) {
510                                            PermissionedModel permissionedModel =
511                                                    ResourceBlockLocalServiceUtil.getPermissionedModel(
512                                                            name, GetterUtil.getLong(primKey));
513    
514                                            long groupId = 0;
515    
516                                            if (permissionedModel instanceof GroupedModel) {
517                                                    GroupedModel groupedModel =
518                                                            (GroupedModel)permissionedModel;
519    
520                                                    groupId = groupedModel.getGroupId();
521                                            }
522    
523                                            ResourceBlockIdsBag resourceBlockIdsBag =
524                                                    getOwnerResourceBlockIdsBag(companyId, groupId, name);
525    
526                                            return ResourceBlockLocalServiceUtil.hasPermission(
527                                                    name, permissionedModel, actionId, resourceBlockIdsBag);
528                                    }
529    
530                                    return ResourcePermissionLocalServiceUtil.hasResourcePermission(
531                                            companyId, name, ResourceConstants.SCOPE_INDIVIDUAL,
532                                            primKey, getOwnerRoleId(), actionId);
533                            }
534    
535                            ResourceActionsUtil.checkAction(name, actionId);
536    
537                            Resource resource = ResourceLocalServiceUtil.getResource(
538                                    companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
539    
540                            List<Permission> permissions =
541                                    PermissionLocalServiceUtil.getRolePermissions(
542                                            getOwnerRoleId(), resource.getResourceId());
543    
544                            int pos = Collections.binarySearch(
545                                    permissions, actionId, new PermissionActionIdComparator());
546    
547                            if (pos >= 0) {
548                                    return true;
549                            }
550                    }
551                    catch (Exception e) {
552                            if (_log.isDebugEnabled()) {
553                                    _log.debug(e, e);
554                            }
555                    }
556    
557                    return false;
558            }
559    
560            @Override
561            public boolean hasPermission(
562                    long groupId, String name, String primKey, String actionId) {
563    
564                    StopWatch stopWatch = null;
565    
566                    if (_log.isDebugEnabled()) {
567                            stopWatch = new StopWatch();
568    
569                            stopWatch.start();
570                    }
571    
572                    Group group = null;
573    
574                    // If the current group is a staging group, check the live group. If the
575                    // current group is a scope group for a layout, check the original
576                    // group.
577    
578                    try {
579                            if (groupId > 0) {
580                                    group = GroupLocalServiceUtil.getGroup(groupId);
581    
582                                    if (group.isUser() && (group.getClassPK() == getUserId())) {
583                                            group = GroupLocalServiceUtil.getGroup(
584                                                    getCompanyId(), GroupConstants.USER_PERSONAL_SITE);
585    
586                                            groupId = group.getGroupId();
587                                    }
588    
589                                    if (group.isLayout() &&
590                                            !ResourceBlockLocalServiceUtil.isSupported(name)) {
591    
592                                            Layout layout = LayoutLocalServiceUtil.getLayout(
593                                                    group.getClassPK());
594    
595                                            groupId = layout.getGroupId();
596    
597                                            group = GroupLocalServiceUtil.getGroup(groupId);
598                                    }
599    
600                                    if (group.isStagingGroup()) {
601                                            if (primKey.equals(String.valueOf(groupId))) {
602                                                    primKey = String.valueOf(group.getLiveGroupId());
603                                            }
604    
605                                            groupId = group.getLiveGroupId();
606                                            group = group.getLiveGroup();
607                                    }
608                            }
609                    }
610                    catch (Exception e) {
611                            _log.error(e, e);
612                    }
613    
614                    Boolean value = PermissionCacheUtil.getPermission(
615                            user.getUserId(), signedIn, checkGuest, groupId, name, primKey,
616                            actionId);
617    
618                    if (value != null) {
619                            return value.booleanValue();
620                    }
621    
622                    try {
623                            value = Boolean.valueOf(
624                                    hasPermissionImpl(groupId, name, primKey, actionId));
625    
626                            if (_log.isDebugEnabled()) {
627                                    _log.debug(
628                                            "Checking permission for " + groupId + " " + name +
629                                                    " " + primKey + " " + actionId + " takes " +
630                                                            stopWatch.getTime() + " ms");
631                            }
632                    }
633                    finally {
634                            if (value == null) {
635                                    value = Boolean.FALSE;
636                            }
637    
638                            PermissionCacheUtil.putPermission(
639                                    user.getUserId(), signedIn, checkGuest, groupId, name, primKey,
640                                    actionId, value);
641                    }
642    
643                    return value.booleanValue();
644            }
645    
646            @Override
647            public boolean hasUserPermission(
648                    long groupId, String name, String primKey, String actionId,
649                    boolean checkAdmin) {
650    
651                    try {
652                            return hasUserPermissionImpl(
653                                    groupId, name, primKey, actionId, checkAdmin);
654                    }
655                    catch (Exception e) {
656                            _log.error(e, e);
657    
658                            return false;
659                    }
660            }
661    
662            @Override
663            public boolean isCompanyAdmin() {
664                    try {
665                            return isCompanyAdminImpl();
666                    }
667                    catch (Exception e) {
668                            _log.error(e, e);
669    
670                            return false;
671                    }
672            }
673    
674            @Override
675            public boolean isCompanyAdmin(long companyId) {
676                    try {
677                            return isCompanyAdminImpl(companyId);
678                    }
679                    catch (Exception e) {
680                            _log.error(e, e);
681    
682                            return false;
683                    }
684            }
685    
686            @Override
687            public boolean isGroupAdmin(long groupId) {
688                    try {
689                            return isGroupAdminImpl(groupId);
690                    }
691                    catch (Exception e) {
692                            _log.error(e, e);
693    
694                            return false;
695                    }
696            }
697    
698            @Override
699            public boolean isGroupMember(long groupId) {
700                    try {
701                            return isGroupMemberImpl(groupId);
702                    }
703                    catch (Exception e) {
704                            _log.error(e, e);
705    
706                            return false;
707                    }
708            }
709    
710            @Override
711            public boolean isGroupOwner(long groupId) {
712                    try {
713                            return isGroupOwnerImpl(groupId);
714                    }
715                    catch (Exception e) {
716                            _log.error(e, e);
717    
718                            return false;
719                    }
720            }
721    
722            @Override
723            public boolean isOrganizationAdmin(long organizationId) {
724                    try {
725                            return isOrganizationAdminImpl(organizationId);
726                    }
727                    catch (Exception e) {
728                            _log.error(e, e);
729    
730                            return false;
731                    }
732            }
733    
734            @Override
735            public boolean isOrganizationOwner(long organizationId) {
736                    try {
737                            return isOrganizationOwnerImpl(organizationId);
738                    }
739                    catch (Exception e) {
740                            _log.error(e, e);
741    
742                            return false;
743                    }
744            }
745    
746            protected void addTeamRoles(long userId, Group group, List<Role> roles)
747                    throws Exception {
748    
749                    if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) ||
750                            (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6)) {
751    
752                            List<Team> userTeams = TeamLocalServiceUtil.getUserTeams(
753                                    userId, group.getGroupId());
754    
755                            for (Team team : userTeams) {
756                                    Role role = RoleLocalServiceUtil.getTeamRole(
757                                            team.getCompanyId(), team.getTeamId());
758    
759                                    roles.add(role);
760                            }
761    
762                            LinkedHashMap<String, Object> teamParams =
763                                    new LinkedHashMap<String, Object>();
764    
765                            teamParams.put("usersUserGroups", userId);
766    
767                            List<Team> userGroupTeams = TeamLocalServiceUtil.search(
768                                    group.getGroupId(), null, null, teamParams, QueryUtil.ALL_POS,
769                                    QueryUtil.ALL_POS, null);
770    
771                            for (Team team : userGroupTeams) {
772                                    Role role = RoleLocalServiceUtil.getTeamRole(
773                                            team.getCompanyId(), team.getTeamId());
774    
775                                    roles.add(role);
776                            }
777                    }
778            }
779    
780            /**
781             * Returns representations of the resource at each scope level.
782             *
783             * <p>
784             * For example, if the class name and primary key of a blog entry were
785             * passed to this method, it would return a resource for the blog entry
786             * itself (individual scope), a resource representing all blog entries
787             * within its group (group scope), a resource standing for all blog entries
788             * within a group the user has a suitable role in (group-template scope),
789             * and a resource signifying all blog entries within the company (company
790             * scope).
791             * </p>
792             *
793             * @param  companyId the primary key of the company
794             * @param  groupId the primary key of the group containing the resource
795             * @param  name the resource's name, which can be either a class name or a
796             *         portlet ID
797             * @param  primKey the primary key of the resource
798             * @param  actionId unused
799             * @return representations of the resource at each scope level
800             * @throws Exception if an exception occurred
801             */
802            protected List<Resource> getResources(
803                            long companyId, long groupId, String name, String primKey,
804                            String actionId)
805                    throws Exception {
806    
807                    // Individual
808    
809                    List<Resource> resources = new ArrayList<Resource>(4);
810    
811                    try {
812                            Resource resource = ResourceLocalServiceUtil.getResource(
813                                    companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
814    
815                            resources.add(resource);
816                    }
817                    catch (NoSuchResourceException nsre) {
818                            if (_log.isWarnEnabled()) {
819                                    _log.warn(
820                                            "Resource " + companyId + " " + name + " " +
821                                                    ResourceConstants.SCOPE_INDIVIDUAL + " " + primKey +
822                                                            " does not exist");
823                            }
824                    }
825    
826                    // Group
827    
828                    try {
829                            if (groupId > 0) {
830                                    Resource resource = ResourceLocalServiceUtil.getResource(
831                                            companyId, name, ResourceConstants.SCOPE_GROUP,
832                                            String.valueOf(groupId));
833    
834                                    resources.add(resource);
835                            }
836                    }
837                    catch (NoSuchResourceException nsre) {
838                            if (_log.isWarnEnabled()) {
839                                    _log.warn(
840                                            "Resource " + companyId + " " + name + " " +
841                                                    ResourceConstants.SCOPE_GROUP + " " + groupId +
842                                                            " does not exist");
843                            }
844                    }
845    
846                    // Group template
847    
848                    try {
849                            if (signedIn && (groupId > 0)) {
850                                    Resource resource = ResourceLocalServiceUtil.getResource(
851                                            companyId, name, ResourceConstants.SCOPE_GROUP_TEMPLATE,
852                                            String.valueOf(GroupConstants.DEFAULT_PARENT_GROUP_ID));
853    
854                                    resources.add(resource);
855                            }
856                    }
857                    catch (NoSuchResourceException nsre) {
858                            if (_log.isWarnEnabled()) {
859                                    _log.warn(
860                                            "Resource " + companyId + " " + name + " " +
861                                                    ResourceConstants.SCOPE_GROUP_TEMPLATE + " " +
862                                                            GroupConstants.DEFAULT_PARENT_GROUP_ID +
863                                                                    " does not exist");
864                            }
865                    }
866    
867                    // Company
868    
869                    try {
870                            Resource resource = ResourceLocalServiceUtil.getResource(
871                                    companyId, name, ResourceConstants.SCOPE_COMPANY,
872                                    String.valueOf(companyId));
873    
874                            resources.add(resource);
875                    }
876                    catch (NoSuchResourceException nsre) {
877                            if (_log.isWarnEnabled()) {
878                                    _log.warn(
879                                            "Resource " + companyId + " " + name + " " +
880                                                    ResourceConstants.SCOPE_COMPANY + " " + companyId +
881                                                            " does not exist");
882                            }
883                    }
884    
885                    return resources;
886            }
887    
888            /**
889             * Returns all of the organizations that the user is a member of, including
890             * their parent organizations.
891             *
892             * @param  userId the primary key of the user
893             * @return all of the organizations that the user is a member of, including
894             *         their parent organizations
895             * @throws Exception if a user with the primary key could not be found
896             */
897            protected List<Organization> getUserOrgs(long userId) throws Exception {
898                    List<Organization> userOrgs =
899                            OrganizationLocalServiceUtil.getUserOrganizations(userId);
900    
901                    if (userOrgs.size() == 0) {
902                            return userOrgs;
903                    }
904    
905                    List<Organization> organizations = new UniqueList<Organization>();
906    
907                    for (Organization organization : userOrgs) {
908                            if (!organizations.contains(organization)) {
909                                    organizations.add(organization);
910    
911                                    List<Organization> ancestorOrganizations =
912                                            OrganizationLocalServiceUtil.getParentOrganizations(
913                                                    organization.getOrganizationId());
914    
915                                    organizations.addAll(ancestorOrganizations);
916                            }
917                    }
918    
919                    return organizations;
920            }
921    
922            protected boolean hasGuestPermission(
923                            long groupId, String name, String primKey, String actionId)
924                    throws Exception {
925    
926                    ResourceActionsUtil.checkAction(name, actionId);
927    
928                    if (name.indexOf(CharPool.PERIOD) != -1) {
929    
930                            // Check unsupported model actions
931    
932                            List<String> actions =
933                                    ResourceActionsUtil.getModelResourceGuestUnsupportedActions(
934                                            name);
935    
936                            if (actions.contains(actionId)) {
937                                    return false;
938                            }
939                    }
940                    else {
941    
942                            // Check unsupported portlet actions
943    
944                            List<String> actions =
945                                    ResourceActionsUtil.getPortletResourceGuestUnsupportedActions(
946                                            name);
947    
948                            if (actions.contains(actionId)) {
949                                    return false;
950                            }
951                    }
952    
953                    long companyId = user.getCompanyId();
954    
955                    List<Resource> resources = getResources(
956                            companyId, groupId, name, primKey, actionId);
957    
958                    PermissionCheckerBag bag = getGuestUserBag();
959    
960                    try {
961                            if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) &&
962                                    ResourceBlockLocalServiceUtil.isSupported(name)) {
963    
964                                    ResourceBlockIdsBag resourceBlockIdsBag =
965                                            getGuestResourceBlockIdsBag(companyId, groupId, name);
966    
967                                    return ResourceBlockLocalServiceUtil.hasPermission(
968                                            name, GetterUtil.getLong(primKey), actionId,
969                                            resourceBlockIdsBag);
970                            }
971    
972                            return PermissionLocalServiceUtil.hasUserPermissions(
973                                    defaultUserId, groupId, resources, actionId, bag);
974                    }
975                    catch (Exception e) {
976                            _log.error(e, e);
977    
978                            return false;
979                    }
980            }
981    
982            protected boolean hasPermissionImpl(
983                    long groupId, String name, String primKey, String actionId) {
984    
985                    try {
986                            if (!signedIn) {
987                                    return hasGuestPermission(groupId, name, primKey, actionId);
988                            }
989    
990                            if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) &&
991                                    ResourceBlockLocalServiceUtil.isSupported(name)) {
992    
993                                    // It is not necessary to check guest permissions separately, as
994                                    // the user's resource block IDs bag will already have the guest
995                                    // permissions in it if checkGuest is true.
996    
997                                    return hasUserPermission(
998                                            groupId, name, primKey, actionId, true);
999                            }
1000    
1001                            boolean value = false;
1002    
1003                            if (checkGuest) {
1004                                    value = hasGuestPermission(groupId, name, primKey, actionId);
1005                            }
1006    
1007                            if (!value) {
1008                                    value = hasUserPermission(
1009                                            groupId, name, primKey, actionId, true);
1010                            }
1011    
1012                            return value;
1013                    }
1014                    catch (Exception e) {
1015                            _log.error(e, e);
1016    
1017                            return false;
1018                    }
1019            }
1020    
1021            protected boolean hasUserPermissionImpl(
1022                            long groupId, String name, String primKey, String actionId,
1023                            boolean checkAdmin)
1024                    throws Exception {
1025    
1026                    StopWatch stopWatch = null;
1027    
1028                    if (_log.isDebugEnabled()) {
1029                            stopWatch = new StopWatch();
1030    
1031                            stopWatch.start();
1032                    }
1033    
1034                    long companyId = user.getCompanyId();
1035    
1036                    boolean hasLayoutManagerPermission = true;
1037    
1038                    // Check if the layout manager has permission to do this action for the
1039                    // current portlet
1040    
1041                    if (Validator.isNotNull(name) && Validator.isNotNull(primKey) &&
1042                            primKey.contains(PortletConstants.LAYOUT_SEPARATOR)) {
1043    
1044                            hasLayoutManagerPermission =
1045                                    PortletPermissionUtil.hasLayoutManagerPermission(
1046                                            name, actionId);
1047                    }
1048    
1049                    if (checkAdmin) {
1050                            if (isCompanyAdminImpl(companyId)) {
1051                                    return true;
1052                            }
1053    
1054                            if (name.equals(Organization.class.getName())) {
1055                                    long organizationId = GetterUtil.getInteger(primKey);
1056    
1057                                    if (isOrganizationAdminImpl(organizationId)) {
1058                                            return true;
1059                                    }
1060                            }
1061                            else if (isGroupAdminImpl(groupId) && hasLayoutManagerPermission) {
1062                                    return true;
1063                            }
1064                    }
1065    
1066                    logHasUserPermission(groupId, name, primKey, actionId, stopWatch, 1);
1067    
1068                    if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) &&
1069                            ResourceBlockLocalServiceUtil.isSupported(name)) {
1070    
1071                            ResourceBlockIdsBag resourceBlockIdsBag = getResourceBlockIdsBag(
1072                                    companyId, groupId, getUserId(), name);
1073    
1074                            boolean value = ResourceBlockLocalServiceUtil.hasPermission(
1075                                    name, GetterUtil.getLong(primKey), actionId,
1076                                    resourceBlockIdsBag);
1077    
1078                            logHasUserPermission(
1079                                    groupId, name, primKey, actionId, stopWatch, 2);
1080    
1081                            return value;
1082                    }
1083    
1084                    List<Resource> resources = getResources(
1085                            companyId, groupId, name, primKey, actionId);
1086    
1087                    logHasUserPermission(groupId, name, primKey, actionId, stopWatch, 3);
1088    
1089                    // Check if user has access to perform the action on the given resource
1090                    // scopes. The resources are scoped to check first for an individual
1091                    // class, then for the group that the class may belong to, and then for
1092                    // the company that the class belongs to.
1093    
1094                    PermissionCheckerBag bag = getUserBag(user.getUserId(), groupId);
1095    
1096                    boolean value = PermissionLocalServiceUtil.hasUserPermissions(
1097                            user.getUserId(), groupId, resources, actionId, bag);
1098    
1099                    logHasUserPermission(groupId, name, primKey, actionId, stopWatch, 4);
1100    
1101                    return value;
1102            }
1103    
1104            protected boolean isCompanyAdminImpl() throws Exception {
1105                    return isCompanyAdminImpl(user.getCompanyId());
1106            }
1107    
1108            protected boolean isCompanyAdminImpl(long companyId) throws Exception {
1109                    if (!signedIn) {
1110                            return false;
1111                    }
1112    
1113                    if (isOmniadmin()) {
1114                            return true;
1115                    }
1116    
1117                    Boolean value = companyAdmins.get(companyId);
1118    
1119                    if (value == null) {
1120                            boolean hasAdminRole = RoleLocalServiceUtil.hasUserRole(
1121                                    user.getUserId(), companyId, RoleConstants.ADMINISTRATOR, true);
1122    
1123                            value = Boolean.valueOf(hasAdminRole);
1124    
1125                            companyAdmins.put(companyId, value);
1126                    }
1127    
1128                    return value.booleanValue();
1129            }
1130    
1131            protected boolean isGroupAdminImpl(long groupId) throws Exception {
1132                    if (!signedIn) {
1133                            return false;
1134                    }
1135    
1136                    if (isOmniadmin()) {
1137                            return true;
1138                    }
1139    
1140                    if (groupId <= 0) {
1141                            return false;
1142                    }
1143    
1144                    Group group = GroupLocalServiceUtil.getGroup(groupId);
1145    
1146                    if (isCompanyAdmin(group.getCompanyId())) {
1147                            return true;
1148                    }
1149    
1150                    PermissionCheckerBag bag = getUserBag(user.getUserId(), groupId);
1151    
1152                    if (bag == null) {
1153                            _log.error("Bag should never be null");
1154                    }
1155    
1156                    if (bag.isGroupAdmin(this, group)) {
1157                            return true;
1158                    }
1159                    else {
1160                            return false;
1161                    }
1162            }
1163    
1164            protected boolean isGroupMemberImpl(long groupId) throws Exception {
1165                    if (!signedIn) {
1166                            return false;
1167                    }
1168    
1169                    if (groupId <= 0) {
1170                            return false;
1171                    }
1172    
1173                    Group group = GroupLocalServiceUtil.getGroup(groupId);
1174    
1175                    PermissionCheckerBag bag = getUserBag(user.getUserId(), groupId);
1176    
1177                    if (bag == null) {
1178                            _log.error("Bag should never be null");
1179                    }
1180    
1181                    if (bag.isGroupMember(this, group)) {
1182                            return true;
1183                    }
1184                    else {
1185                            return false;
1186                    }
1187            }
1188    
1189            protected boolean isGroupOwnerImpl(long groupId) throws Exception {
1190                    if (!signedIn) {
1191                            return false;
1192                    }
1193    
1194                    if (isOmniadmin()) {
1195                            return true;
1196                    }
1197    
1198                    if (groupId <= 0) {
1199                            return false;
1200                    }
1201    
1202                    Group group = GroupLocalServiceUtil.getGroup(groupId);
1203    
1204                    if (isCompanyAdmin(group.getCompanyId())) {
1205                            return true;
1206                    }
1207    
1208                    PermissionCheckerBag bag = getUserBag(user.getUserId(), groupId);
1209    
1210                    if (bag == null) {
1211                            _log.error("Bag should never be null");
1212                    }
1213    
1214                    if (bag.isGroupOwner(this, group)) {
1215                            return true;
1216                    }
1217                    else {
1218                            return false;
1219                    }
1220            }
1221    
1222            protected boolean isOrganizationAdminImpl(long organizationId)
1223                    throws Exception {
1224    
1225                    if (!signedIn) {
1226                            return false;
1227                    }
1228    
1229                    if (isOmniadmin()) {
1230                            return true;
1231                    }
1232    
1233                    if (organizationId <= 0) {
1234                            return false;
1235                    }
1236    
1237                    Organization organization =
1238                            OrganizationLocalServiceUtil.fetchOrganization(organizationId);
1239    
1240                    if (organization == null) {
1241                            return false;
1242                    }
1243    
1244                    if (isCompanyAdmin(organization.getCompanyId())) {
1245                            return true;
1246                    }
1247    
1248                    PermissionCheckerBag bag = getUserBag(
1249                            user.getUserId(), organization.getGroupId());
1250    
1251                    if (bag == null) {
1252                            _log.error("Bag should never be null");
1253                    }
1254    
1255                    if (bag.isOrganizationAdmin(this, organization)) {
1256                            return true;
1257                    }
1258                    else {
1259                            return false;
1260                    }
1261            }
1262    
1263            protected boolean isOrganizationOwnerImpl(long organizationId)
1264                    throws Exception {
1265    
1266                    if (!signedIn) {
1267                            return false;
1268                    }
1269    
1270                    if (isOmniadmin()) {
1271                            return true;
1272                    }
1273    
1274                    if (organizationId <= 0) {
1275                            return false;
1276                    }
1277    
1278                    Organization organization =
1279                            OrganizationLocalServiceUtil.fetchOrganization(organizationId);
1280    
1281                    if (organization == null) {
1282                            return false;
1283                    }
1284    
1285                    if (isCompanyAdmin(organization.getCompanyId())) {
1286                            return true;
1287                    }
1288    
1289                    PermissionCheckerBag bag = getUserBag(
1290                            user.getUserId(), organization.getGroupId());
1291    
1292                    if (bag == null) {
1293                            _log.error("Bag should never be null");
1294                    }
1295    
1296                    if (bag.isOrganizationOwner(this, organization)) {
1297                            return true;
1298                    }
1299                    else {
1300                            return false;
1301                    }
1302            }
1303    
1304            protected void logHasUserPermission(
1305                    long groupId, String name, String primKey, String actionId,
1306                    StopWatch stopWatch, int block) {
1307    
1308                    if (!_log.isDebugEnabled()) {
1309                            return;
1310                    }
1311    
1312                    _log.debug(
1313                            "Checking user permission block " + block + " for " + groupId +
1314                                    " " + name + " " + primKey + " " + actionId + " takes " +
1315                                            stopWatch.getTime() + " ms");
1316            }
1317    
1318            /**
1319             * @deprecated
1320             */
1321            protected static final String RESULTS_SEPARATOR = "_RESULTS_SEPARATOR_";
1322    
1323            protected Map<Long, Boolean> companyAdmins = new HashMap<Long, Boolean>();
1324    
1325            private static Log _log = LogFactoryUtil.getLog(
1326                    AdvancedPermissionChecker.class);
1327    
1328    }