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.verify;
016    
017    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
018    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
019    import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
020    import com.liferay.portal.kernel.dao.orm.RestrictionsFactoryUtil;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.util.GetterUtil;
024    import com.liferay.portal.kernel.util.StringBundler;
025    import com.liferay.portal.model.Group;
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.Resource;
030    import com.liferay.portal.model.ResourceCode;
031    import com.liferay.portal.model.ResourceConstants;
032    import com.liferay.portal.model.ResourcePermission;
033    import com.liferay.portal.model.Role;
034    import com.liferay.portal.model.RoleConstants;
035    import com.liferay.portal.security.permission.ActionKeys;
036    import com.liferay.portal.security.permission.PermissionCacheUtil;
037    import com.liferay.portal.security.permission.ResourceActionsUtil;
038    import com.liferay.portal.service.LayoutLocalServiceUtil;
039    import com.liferay.portal.service.PermissionLocalServiceUtil;
040    import com.liferay.portal.service.ResourceActionLocalServiceUtil;
041    import com.liferay.portal.service.ResourceCodeLocalServiceUtil;
042    import com.liferay.portal.service.ResourceLocalServiceUtil;
043    import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
044    import com.liferay.portal.service.RoleLocalServiceUtil;
045    import com.liferay.portal.service.UserLocalServiceUtil;
046    import com.liferay.portal.service.impl.ResourcePermissionLocalServiceImpl;
047    import com.liferay.portal.util.PortalInstances;
048    import com.liferay.portal.util.PropsValues;
049    
050    import java.sql.Connection;
051    import java.sql.PreparedStatement;
052    import java.sql.ResultSet;
053    
054    import java.util.List;
055    
056    /**
057     * @author Tobias Kaefer
058     * @author Douglas Wong
059     * @author Matthew Kong
060     * @author Raymond Aug??
061     */
062    public class VerifyPermission
063            extends VerifyProcess implements ResourceConstants {
064    
065            protected void checkPermissions() throws Exception {
066                    List<String> modelNames = ResourceActionsUtil.getModelNames();
067    
068                    for (String modelName : modelNames) {
069                            List<String> actionIds =
070                                    ResourceActionsUtil.getModelResourceActions(modelName);
071    
072                            if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
073                                    PermissionLocalServiceUtil.checkPermissions(
074                                            modelName, actionIds);
075                            }
076                            else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
077                                    ResourceActionLocalServiceUtil.checkResourceActions(
078                                            modelName, actionIds, true);
079                            }
080                    }
081            }
082    
083            protected void deleteDefaultPrivateLayoutPermissions() throws Exception {
084                    long[] companyIds = PortalInstances.getCompanyIdsBySQL();
085    
086                    for (long companyId : companyIds) {
087                            try {
088                                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
089                                            deleteDefaultPrivateLayoutPermissions_5(companyId);
090                                    }
091                                    else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
092                                            deleteDefaultPrivateLayoutPermissions_6(companyId);
093                                    }
094                                    else {
095                                            deleteDefaultPrivateLayoutPermissions_1to4(companyId);
096                                    }
097                            }
098                            catch (Exception e) {
099                                    if (_log.isDebugEnabled()) {
100                                            _log.debug(e, e);
101                                    }
102                            }
103                    }
104            }
105    
106            protected void deleteDefaultPrivateLayoutPermissions_1to4(long companyId)
107                    throws Exception {
108    
109                    long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
110    
111                    List<Permission> permissions =
112                            PermissionLocalServiceUtil.getUserPermissions(defaultUserId);
113    
114                    for (Permission permission : permissions) {
115                            Resource resource = ResourceLocalServiceUtil.getResource(
116                                    permission.getResourceId());
117    
118                            ResourceCode resourceCode =
119                                    ResourceCodeLocalServiceUtil.getResourceCode(
120                                            resource.getCodeId());
121    
122                            if (isPrivateLayout(
123                                            resourceCode.getName(), resource.getPrimKey())) {
124    
125                                    String[] actionIds = new String[] {permission.getActionId()};
126    
127                                    PermissionLocalServiceUtil.unsetUserPermissions(
128                                            defaultUserId, actionIds, permission.getResourceId());
129                            }
130                    }
131            }
132    
133            protected void deleteDefaultPrivateLayoutPermissions_5(long companyId)
134                    throws Exception {
135    
136                    Role role = RoleLocalServiceUtil.getRole(
137                            companyId, RoleConstants.GUEST);
138    
139                    List<Permission> permissions =
140                            PermissionLocalServiceUtil.getRolePermissions(role.getRoleId());
141    
142                    for (Permission permission : permissions) {
143                            Resource resource = ResourceLocalServiceUtil.getResource(
144                                    permission.getResourceId());
145    
146                            ResourceCode resourceCode =
147                                    ResourceCodeLocalServiceUtil.getResourceCode(
148                                            resource.getCodeId());
149    
150                            if (isPrivateLayout(
151                                            resourceCode.getName(), resource.getPrimKey())) {
152    
153                                    PermissionLocalServiceUtil.unsetRolePermission(
154                                            role.getRoleId(), permission.getPermissionId());
155                            }
156                    }
157            }
158    
159            protected void deleteDefaultPrivateLayoutPermissions_6(long companyId)
160                    throws Exception {
161    
162                    Role role = RoleLocalServiceUtil.getRole(
163                            companyId, RoleConstants.GUEST);
164    
165                    List<ResourcePermission> resourcePermissions =
166                            ResourcePermissionLocalServiceUtil.getRoleResourcePermissions(
167                                    role.getRoleId());
168    
169                    for (ResourcePermission resourcePermission : resourcePermissions) {
170                            if (isPrivateLayout(
171                                            resourcePermission.getName(),
172                                            resourcePermission.getPrimKey())) {
173    
174                                    ResourcePermissionLocalServiceUtil.deleteResourcePermission(
175                                            resourcePermission.getResourcePermissionId());
176                            }
177                    }
178            }
179    
180            @Override
181            protected void doVerify() throws Exception {
182                    deleteDefaultPrivateLayoutPermissions();
183    
184                    if ((PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM != 5) &&
185                            (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM != 6)) {
186    
187                            return;
188                    }
189    
190                    checkPermissions();
191                    fixLayoutRolePermissions();
192                    fixOrganizationRolePermissions();
193            }
194    
195            protected void fixLayoutRolePermissions() throws Exception {
196                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM != 6) {
197                            return;
198                    }
199    
200                    fixLayoutRolePermissions_6();
201    
202                    PermissionCacheUtil.clearCache();
203            }
204    
205            /**
206             * Fixes the case where layouts are missing the required owner role
207             * permissions. This can happen when upgrading from permission algorithms 1,
208             * 2, 3, and 4 to algorithm 6. This method will check for the presence of
209             * the owner role's resource permission for all layouts. The resource
210             * permission will be created if it does not exist. Both existing or newly
211             * created resource permission default action IDs for owner role are
212             * checked. If owner permissions for default action ID is missing, then the
213             * permission is given to the owner. See LPS-26191.
214             */
215            protected void fixLayoutRolePermissions_6() throws Exception {
216                    List<String> actions = ResourceActionsUtil.getModelResourceActions(
217                            Layout.class.getName());
218    
219                    String[] actionIds = actions.toArray(new String[actions.size()]);
220    
221                    Connection con = null;
222                    PreparedStatement ps = null;
223                    ResultSet rs = null;
224    
225                    try {
226                            con = DataAccess.getUpgradeOptimizedConnection();
227    
228                            StringBundler sb = new StringBundler(4);
229    
230                            sb.append("select Layout.companyId as companyId, Layout.plid as ");
231                            sb.append("primKey, Role_.roleId as ownerRoleId from Role_, ");
232                            sb.append("Layout where Role_.companyId = Layout.companyId and ");
233                            sb.append("Role_.name = ?");
234    
235                            ps = con.prepareStatement(sb.toString());
236    
237                            ps.setString(1, RoleConstants.OWNER);
238    
239                            rs = ps.executeQuery();
240    
241                            while (rs.next()) {
242                                    long companyId = rs.getLong("companyId");
243                                    String primKey = String.valueOf(rs.getLong("primKey"));
244                                    long ownerRoleId = rs.getLong("ownerRoleId");
245    
246                                    fixLayoutRolePermissions_6(
247                                            companyId, primKey, ownerRoleId, actionIds);
248                            }
249                    }
250                    finally {
251                            DataAccess.cleanUp(con, ps, rs);
252                    }
253            }
254    
255            protected void fixLayoutRolePermissions_6(
256                            long companyId, String primKey, long ownerRoleId,
257                            String[] actionIds)
258                    throws Exception {
259    
260                    if (hasResourcePermission(companyId, primKey, ownerRoleId)) {
261                            return;
262                    }
263    
264                    ResourcePermissionLocalServiceUtil.setResourcePermissions(
265                            companyId, Layout.class.getName(), SCOPE_INDIVIDUAL, primKey,
266                            ownerRoleId, actionIds);
267    
268                    ResourcePermissionLocalServiceUtil.getResourcePermission(
269                            companyId, Layout.class.getName(), SCOPE_INDIVIDUAL, primKey,
270                            ownerRoleId);
271            }
272    
273            protected void fixOrganizationRolePermissions() throws Exception {
274                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
275                            fixOrganizationRolePermissions_5();
276                    }
277                    else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
278                            fixOrganizationRolePermissions_6();
279                    }
280    
281                    PermissionCacheUtil.clearCache();
282            }
283    
284            protected void fixOrganizationRolePermissions_5() throws Exception {
285                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
286                            ResourceCode.class);
287    
288                    dynamicQuery.add(
289                            RestrictionsFactoryUtil.eq("name", Organization.class.getName()));
290    
291                    List<ResourceCode> resouceCodes =
292                            ResourceCodeLocalServiceUtil.dynamicQuery(dynamicQuery);
293    
294                    for (ResourceCode resourceCode : resouceCodes) {
295                            dynamicQuery = DynamicQueryFactoryUtil.forClass(Resource.class);
296    
297                            dynamicQuery.add(
298                                    RestrictionsFactoryUtil.eq("codeId", resourceCode.getCodeId()));
299    
300                            List<Resource> resources = ResourceLocalServiceUtil.dynamicQuery(
301                                    dynamicQuery);
302    
303                            for (Resource resource : resources) {
304                                    dynamicQuery = DynamicQueryFactoryUtil.forClass(
305                                            Permission.class);
306    
307                                    dynamicQuery.add(
308                                            RestrictionsFactoryUtil.eq(
309                                                    "resourceId", resource.getResourceId()));
310    
311                                    List<Permission> permissions =
312                                            PermissionLocalServiceUtil.dynamicQuery(dynamicQuery);
313    
314                                    processPermissions(resource, permissions);
315                            }
316                    }
317            }
318    
319            protected void fixOrganizationRolePermissions_6() throws Exception {
320                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
321                            ResourcePermission.class);
322    
323                    dynamicQuery.add(
324                            RestrictionsFactoryUtil.eq("name", Organization.class.getName()));
325    
326                    List<ResourcePermission> resourcePermissions =
327                            ResourcePermissionLocalServiceUtil.dynamicQuery(dynamicQuery);
328    
329                    for (ResourcePermission resourcePermission : resourcePermissions) {
330                            ResourcePermission groupResourcePermission = null;
331    
332                            try {
333                                    groupResourcePermission =
334                                            ResourcePermissionLocalServiceUtil.getResourcePermission(
335                                                    resourcePermission.getCompanyId(),
336                                                    Group.class.getName(), resourcePermission.getScope(),
337                                                    resourcePermission.getPrimKey(),
338                                                    resourcePermission.getRoleId());
339                            }
340                            catch (Exception e) {
341                                    ResourcePermissionLocalServiceUtil.setResourcePermissions(
342                                            resourcePermission.getCompanyId(), Group.class.getName(),
343                                            resourcePermission.getScope(),
344                                            resourcePermission.getPrimKey(),
345                                            resourcePermission.getRoleId(),
346                                            ResourcePermissionLocalServiceImpl.EMPTY_ACTION_IDS);
347    
348                                    groupResourcePermission =
349                                            ResourcePermissionLocalServiceUtil.getResourcePermission(
350                                                    resourcePermission.getCompanyId(),
351                                                    Group.class.getName(), resourcePermission.getScope(),
352                                                    resourcePermission.getPrimKey(),
353                                                    resourcePermission.getRoleId());
354                            }
355    
356                            long organizationActions = resourcePermission.getActionIds();
357                            long groupActions = groupResourcePermission.getActionIds();
358    
359                            for (Object[] actionIdToMask : _ORGANIZATION_ACTION_IDS_TO_MASKS) {
360                                    long organizationActionMask = (Long)actionIdToMask[1];
361                                    long groupActionMask = (Long)actionIdToMask[2];
362    
363                                    if ((organizationActions & organizationActionMask) ==
364                                                    organizationActionMask) {
365    
366                                            organizationActions =
367                                                    organizationActions & (~organizationActionMask);
368                                            groupActions = groupActions | groupActionMask;
369                                    }
370                            }
371    
372                            try {
373                                    resourcePermission.resetOriginalValues();
374    
375                                    resourcePermission.setActionIds(organizationActions);
376    
377                                    ResourcePermissionLocalServiceUtil.updateResourcePermission(
378                                            resourcePermission, false);
379    
380                                    groupResourcePermission.resetOriginalValues();
381                                    groupResourcePermission.setActionIds(groupActions);
382    
383                                    ResourcePermissionLocalServiceUtil.updateResourcePermission(
384                                            groupResourcePermission, false);
385                            }
386                            catch (Exception e) {
387                                    _log.error(e, e);
388                            }
389                    }
390            }
391    
392            protected boolean hasPermission(String actionId, long resourceId)
393                    throws Exception {
394    
395                    Connection con = null;
396                    PreparedStatement ps = null;
397                    ResultSet rs = null;
398    
399                    try {
400                            con = DataAccess.getUpgradeOptimizedConnection();
401    
402                            ps = con.prepareStatement(
403                                    "select count(*) from Permission_ where actionId = ? and " +
404                                            "resourceId = ?");
405    
406                            ps.setString(1, actionId);
407                            ps.setLong(2, resourceId);
408    
409                            rs = ps.executeQuery();
410    
411                            while (rs.next()) {
412                                    int count = rs.getInt(1);
413    
414                                    if (count > 0) {
415                                            return true;
416                                    }
417                            }
418    
419                            return false;
420                    }
421                    finally {
422                            DataAccess.cleanUp(con, ps, rs);
423                    }
424            }
425    
426            protected boolean hasResourcePermission(
427                            long companyId, String primKey, long roleId)
428                    throws Exception {
429    
430                    Connection con = null;
431                    PreparedStatement ps = null;
432                    ResultSet rs = null;
433    
434                    try {
435                            con = DataAccess.getUpgradeOptimizedConnection();
436    
437                            StringBundler sb = new StringBundler(4);
438    
439                            sb.append("select count(*) from ResourcePermission where ");
440                            sb.append("ResourcePermission.companyId = ? and ");
441                            sb.append("ResourcePermission.primKey = ? and ");
442                            sb.append("ResourcePermission.roleId = ?");
443    
444                            ps = con.prepareStatement(sb.toString());
445    
446                            ps.setLong(1, companyId);
447                            ps.setString(2, primKey);
448                            ps.setLong(3, roleId);
449    
450                            rs = ps.executeQuery();
451    
452                            while (rs.next()) {
453                                    int count = rs.getInt(1);
454    
455                                    if (count > 0) {
456                                            return true;
457                                    }
458                            }
459    
460                            return false;
461                    }
462                    finally {
463                            DataAccess.cleanUp(con, ps, rs);
464                    }
465            }
466    
467            protected boolean isPrivateLayout(String name, String primKey)
468                    throws Exception {
469    
470                    if (!name.equals(Layout.class.getName())) {
471                            return false;
472                    }
473    
474                    long plid = GetterUtil.getLong(primKey);
475    
476                    Layout layout = LayoutLocalServiceUtil.getLayout(plid);
477    
478                    if (layout.isPublicLayout() || layout.isTypeControlPanel()) {
479                            return false;
480                    }
481    
482                    return true;
483            }
484    
485            protected void processPermissions(
486                            Resource resource, List<Permission> permissions)
487                    throws Exception {
488    
489                    Resource groupResource = ResourceLocalServiceUtil.fetchResource(
490                            resource.getCompanyId(), Group.class.getName(), resource.getScope(),
491                            resource.getPrimKey());
492    
493                    if (groupResource == null) {
494                            groupResource = ResourceLocalServiceUtil.addResource(
495                                    resource.getCompanyId(), Group.class.getName(),
496                                    resource.getScope(), resource.getPrimKey());
497                    }
498    
499                    for (Permission permission : permissions) {
500                            for (Object[] actionIdToMask : _ORGANIZATION_ACTION_IDS_TO_MASKS) {
501                                    String actionId = (String)actionIdToMask[0];
502                                    long mask = (Long)actionIdToMask[2];
503    
504                                    if (!actionId.equals(permission.getActionId())) {
505                                            continue;
506                                    }
507    
508                                    try {
509                                            if ((mask != 0L) &&
510                                                    !hasPermission(actionId, permission.getResourceId())) {
511    
512                                                    permission.resetOriginalValues();
513    
514                                                    permission.setResourceId(groupResource.getResourceId());
515    
516                                                    PermissionLocalServiceUtil.updatePermission(
517                                                            permission, false);
518                                            }
519                                            else {
520                                                    PermissionLocalServiceUtil.deletePermission(
521                                                            permission.getPermissionId());
522                                            }
523                                    }
524                                    catch (Exception e) {
525                                            _log.error(e, e);
526                                    }
527    
528                                    break;
529                            }
530                    }
531            }
532    
533            private static final Object[][] _ORGANIZATION_ACTION_IDS_TO_MASKS =
534                    new Object[][] {
535                            new Object[] {"APPROVE_PROPOSAL", 2L, 0L},
536                            new Object[] {ActionKeys.ASSIGN_MEMBERS, 4L, 4L},
537                            new Object[] {"ASSIGN_REVIEWER", 8L, 0L},
538                            new Object[] {ActionKeys.MANAGE_ARCHIVED_SETUPS, 128L, 128L},
539                            new Object[] {ActionKeys.MANAGE_LAYOUTS, 256L, 256L},
540                            new Object[] {ActionKeys.MANAGE_STAGING, 512L, 512L},
541                            new Object[] {ActionKeys.MANAGE_TEAMS, 2048L, 1024L},
542                            new Object[] {ActionKeys.PUBLISH_STAGING, 16384L, 4096L}
543                    };
544    
545            private static Log _log = LogFactoryUtil.getLog(VerifyPermission.class);
546    
547    }