001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.verify;
016    
017    import com.liferay.portal.dao.orm.common.SQLTransformer;
018    import com.liferay.portal.kernel.dao.db.DB;
019    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
020    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
021    import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
022    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
023    import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
024    import com.liferay.portal.kernel.dao.orm.EntityCacheUtil;
025    import com.liferay.portal.kernel.dao.orm.FinderCacheUtil;
026    import com.liferay.portal.kernel.dao.orm.Property;
027    import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
028    import com.liferay.portal.kernel.dao.orm.RestrictionsFactoryUtil;
029    import com.liferay.portal.kernel.exception.PortalException;
030    import com.liferay.portal.kernel.exception.SystemException;
031    import com.liferay.portal.kernel.log.Log;
032    import com.liferay.portal.kernel.log.LogFactoryUtil;
033    import com.liferay.portal.kernel.util.CharPool;
034    import com.liferay.portal.kernel.util.GetterUtil;
035    import com.liferay.portal.kernel.util.StringBundler;
036    import com.liferay.portal.kernel.util.StringPool;
037    import com.liferay.portal.kernel.util.StringUtil;
038    import com.liferay.portal.model.Group;
039    import com.liferay.portal.model.Layout;
040    import com.liferay.portal.model.LayoutConstants;
041    import com.liferay.portal.model.Organization;
042    import com.liferay.portal.model.PortletConstants;
043    import com.liferay.portal.model.ResourceConstants;
044    import com.liferay.portal.model.ResourcePermission;
045    import com.liferay.portal.model.Role;
046    import com.liferay.portal.model.RoleConstants;
047    import com.liferay.portal.model.User;
048    import com.liferay.portal.model.UserGroup;
049    import com.liferay.portal.security.permission.ActionKeys;
050    import com.liferay.portal.security.permission.PermissionCacheUtil;
051    import com.liferay.portal.security.permission.ResourceActionsUtil;
052    import com.liferay.portal.service.LayoutLocalServiceUtil;
053    import com.liferay.portal.service.ResourceActionLocalServiceUtil;
054    import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
055    import com.liferay.portal.service.RoleLocalServiceUtil;
056    import com.liferay.portal.service.impl.ResourcePermissionLocalServiceImpl;
057    import com.liferay.portal.service.persistence.ResourcePermissionActionableDynamicQuery;
058    import com.liferay.portal.upgrade.AutoBatchPreparedStatementUtil;
059    import com.liferay.portal.util.PortalInstances;
060    import com.liferay.portal.util.PortalUtil;
061    
062    import java.sql.Connection;
063    import java.sql.PreparedStatement;
064    import java.sql.ResultSet;
065    import java.sql.SQLException;
066    
067    import java.util.ArrayList;
068    import java.util.List;
069    
070    /**
071     * @author Tobias Kaefer
072     * @author Douglas Wong
073     * @author Matthew Kong
074     * @author Raymond Aug??
075     */
076    public class VerifyPermission extends VerifyProcess {
077    
078            protected void checkPermissions() throws Exception {
079                    List<String> modelNames = ResourceActionsUtil.getModelNames();
080    
081                    for (String modelName : modelNames) {
082                            List<String> actionIds =
083                                    ResourceActionsUtil.getModelResourceActions(modelName);
084    
085                                    ResourceActionLocalServiceUtil.checkResourceActions(
086                                            modelName, actionIds, true);
087                    }
088    
089                    List<String> portletNames = ResourceActionsUtil.getPortletNames();
090    
091                    for (String portletName : portletNames) {
092                            List<String> actionIds =
093                                    ResourceActionsUtil.getPortletResourceActions(portletName);
094    
095                            ResourceActionLocalServiceUtil.checkResourceActions(
096                                    portletName, actionIds, true);
097                    }
098            }
099    
100            protected void deleteConflictingUserDefaultRolePermissions(
101                            long companyId, long powerUserRoleId, long userRoleId,
102                            long userClassNameId, long userGroupClassNameId)
103                    throws Exception {
104    
105                    Connection con = null;
106                    PreparedStatement ps1 = null;
107                    PreparedStatement ps2 = null;
108                    ResultSet rs = null;
109    
110                    try {
111                            con = DataAccess.getUpgradeOptimizedConnection();
112    
113                            StringBundler sb = new StringBundler(14);
114    
115                            sb.append("select resourcePermission1.resourcePermissionId from ");
116                            sb.append("ResourcePermission resourcePermission1 inner join ");
117                            sb.append("ResourcePermission resourcePermission2 on ");
118                            sb.append("resourcePermission1.companyId = ");
119                            sb.append("resourcePermission2.companyId and ");
120                            sb.append("resourcePermission1.name = resourcePermission2.name ");
121                            sb.append("and resourcePermission1.scope = ");
122                            sb.append("resourcePermission2.scope and ");
123                            sb.append("resourcePermission1.primKey = ");
124                            sb.append("resourcePermission2.primKey inner join Layout on ");
125                            sb.append("resourcePermission1.companyId = Layout.companyId and ");
126                            sb.append("resourcePermission1.primKey like ");
127                            sb.append("replace('[$PLID$]_LAYOUT_%', '[$PLID$]', ");
128                            sb.append("cast_text(Layout.plid)) and Layout.type_ = '");
129                            sb.append(LayoutConstants.TYPE_PORTLET);
130                            sb.append(CharPool.APOSTROPHE);
131                            sb.append(" inner join Group_ on Layout.groupId = Group_.groupId ");
132                            sb.append("where resourcePermission1.companyId = ");
133                            sb.append(companyId);
134                            sb.append(" and resourcePermission1.roleId = ");
135                            sb.append(powerUserRoleId);
136                            sb.append(" and resourcePermission2.roleId = ");
137                            sb.append(userRoleId);
138                            sb.append(" and resourcePermission1.scope = ");
139                            sb.append(ResourceConstants.SCOPE_INDIVIDUAL);
140                            sb.append(" and (Group_.classNameId = ");
141                            sb.append(userClassNameId);
142                            sb.append(" or Group_.classNameId = ");
143                            sb.append(userGroupClassNameId);
144                            sb.append(")");
145    
146                            String sql = SQLTransformer.transform(sb.toString());
147    
148                            ps1 = con.prepareStatement(sql);
149    
150                            rs = ps1.executeQuery();
151    
152                            ps2 = AutoBatchPreparedStatementUtil.autoBatch(
153                                    con.prepareStatement(
154                                            "delete from ResourcePermission where " +
155                                                    "resourcePermissionId = ?"));
156    
157                            while (rs.next()) {
158                                    ps2.setLong(1, rs.getLong(1));
159    
160                                    ps2.addBatch();
161                            }
162    
163                            ps2.executeBatch();
164                    }
165                    finally {
166                            DataAccess.cleanUp(ps1);
167                            DataAccess.cleanUp(con, ps2, rs);
168                    }
169            }
170    
171            protected void deleteDefaultPrivateLayoutPermissions() throws Exception {
172                    long[] companyIds = PortalInstances.getCompanyIdsBySQL();
173    
174                    for (long companyId : companyIds) {
175                            try {
176                                    deleteDefaultPrivateLayoutPermissions_6(companyId);
177                            }
178                            catch (Exception e) {
179                                    if (_log.isDebugEnabled()) {
180                                            _log.debug(e, e);
181                                    }
182                            }
183                    }
184            }
185    
186            protected void deleteDefaultPrivateLayoutPermissions_6(long companyId)
187                    throws Exception {
188    
189                    Role role = RoleLocalServiceUtil.getRole(
190                            companyId, RoleConstants.GUEST);
191    
192                    final long roleId = role.getRoleId();
193    
194                    ActionableDynamicQuery actionableDynamicQuery =
195                            new ResourcePermissionActionableDynamicQuery() {
196    
197                                    @Override
198                                    public void addCriteria(DynamicQuery dynamicQuery) {
199                                            Property property = PropertyFactoryUtil.forName("roleId");
200    
201                                            dynamicQuery.add(property.eq(roleId));
202                                    }
203    
204                                    @Override
205                                    public void performAction(Object object)
206                                            throws PortalException, SystemException {
207    
208                                            ResourcePermission resourcePermission =
209                                                    (ResourcePermission)object;
210    
211                                            if (isPrivateLayout(
212                                                            resourcePermission.getName(),
213                                                            resourcePermission.getPrimKey())) {
214    
215                                                    ResourcePermissionLocalServiceUtil.
216                                                            deleteResourcePermission(
217                                                                    resourcePermission.getResourcePermissionId());
218                                            }
219                                    }
220                            };
221    
222                    actionableDynamicQuery.performActions();
223            }
224    
225            @Override
226            protected void doVerify() throws Exception {
227                    deleteDefaultPrivateLayoutPermissions();
228    
229                    checkPermissions();
230                    fixOrganizationRolePermissions();
231                    fixUserDefaultRolePermissions();
232            }
233    
234            protected void fixOrganizationRolePermissions() throws Exception {
235                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
236                            ResourcePermission.class);
237    
238                    dynamicQuery.add(
239                            RestrictionsFactoryUtil.eq("name", Organization.class.getName()));
240    
241                    List<ResourcePermission> resourcePermissions =
242                            ResourcePermissionLocalServiceUtil.dynamicQuery(dynamicQuery);
243    
244                    for (ResourcePermission resourcePermission : resourcePermissions) {
245                            ResourcePermission groupResourcePermission = null;
246    
247                            try {
248                                    groupResourcePermission =
249                                            ResourcePermissionLocalServiceUtil.getResourcePermission(
250                                                    resourcePermission.getCompanyId(),
251                                                    Group.class.getName(), resourcePermission.getScope(),
252                                                    resourcePermission.getPrimKey(),
253                                                    resourcePermission.getRoleId());
254                            }
255                            catch (Exception e) {
256                                    ResourcePermissionLocalServiceUtil.setResourcePermissions(
257                                            resourcePermission.getCompanyId(), Group.class.getName(),
258                                            resourcePermission.getScope(),
259                                            resourcePermission.getPrimKey(),
260                                            resourcePermission.getRoleId(),
261                                            ResourcePermissionLocalServiceImpl.EMPTY_ACTION_IDS);
262    
263                                    groupResourcePermission =
264                                            ResourcePermissionLocalServiceUtil.getResourcePermission(
265                                                    resourcePermission.getCompanyId(),
266                                                    Group.class.getName(), resourcePermission.getScope(),
267                                                    resourcePermission.getPrimKey(),
268                                                    resourcePermission.getRoleId());
269                            }
270    
271                            for (String actionId : _DEPRECATED_ORGANIZATION_ACTION_IDS) {
272                                    if (resourcePermission.hasActionId(actionId)) {
273                                            resourcePermission.removeResourceAction(actionId);
274    
275                                            groupResourcePermission.addResourceAction(actionId);
276                                    }
277                            }
278    
279                            try {
280                                    resourcePermission.resetOriginalValues();
281    
282                                    ResourcePermissionLocalServiceUtil.updateResourcePermission(
283                                            resourcePermission);
284    
285                                    groupResourcePermission.resetOriginalValues();
286    
287                                    ResourcePermissionLocalServiceUtil.updateResourcePermission(
288                                            groupResourcePermission);
289                            }
290                            catch (Exception e) {
291                                    _log.error(e, e);
292                            }
293                    }
294    
295                    PermissionCacheUtil.clearResourceCache();
296            }
297    
298            protected void fixUserDefaultRolePermissions() throws Exception {
299                    DB db = DBFactoryUtil.getDB();
300    
301                    String dbType = db.getType();
302    
303                    try {
304                            long userClassNameId = PortalUtil.getClassNameId(User.class);
305                            long userGroupClassNameId = PortalUtil.getClassNameId(
306                                    UserGroup.class);
307    
308                            long[] companyIds = PortalInstances.getCompanyIdsBySQL();
309    
310                            if (dbType.equals(DB.TYPE_MYSQL)) {
311                                    fixUserDefaultRolePermissionsMySQL(
312                                            userClassNameId, userGroupClassNameId, companyIds);
313    
314                                    return;
315                            }
316    
317                            if (dbType.equals(DB.TYPE_ORACLE)) {
318                                    fixUserDefaultRolePermissionsOracle(
319                                            userClassNameId, userGroupClassNameId, companyIds);
320    
321                                    return;
322                            }
323    
324                            for (long companyId : companyIds) {
325                                    Role powerUserRole = RoleLocalServiceUtil.getRole(
326                                            companyId, RoleConstants.POWER_USER);
327                                    Role userRole = RoleLocalServiceUtil.getRole(
328                                            companyId, RoleConstants.USER);
329    
330                                    deleteConflictingUserDefaultRolePermissions(
331                                            companyId, powerUserRole.getRoleId(), userRole.getRoleId(),
332                                            userClassNameId, userGroupClassNameId);
333    
334                                    StringBundler sb = new StringBundler(20);
335    
336                                    sb.append("update ResourcePermission set roleId = ");
337                                    sb.append(userRole.getRoleId());
338                                    sb.append(" where resourcePermissionId in (select ");
339                                    sb.append("resourcePermissionId from ResourcePermission ");
340                                    sb.append("inner join Layout on ResourcePermission.companyId ");
341                                    sb.append("= Layout.companyId and ResourcePermission.primKey ");
342                                    sb.append("like replace('[$PLID$]_LAYOUT_%', '[$PLID$]', ");
343                                    sb.append("cast_text(Layout.plid)) inner join Group_ on ");
344                                    sb.append("Layout.groupId = Group_.groupId where ");
345                                    sb.append("ResourcePermission.scope = ");
346                                    sb.append(ResourceConstants.SCOPE_INDIVIDUAL);
347                                    sb.append(" and ResourcePermission.roleId = ");
348                                    sb.append(powerUserRole.getRoleId());
349                                    sb.append(" and (Group_.classNameId = ");
350                                    sb.append(userClassNameId);
351                                    sb.append(" or Group_.classNameId = ");
352                                    sb.append(userGroupClassNameId);
353                                    sb.append(") and Layout.type_ = '");
354                                    sb.append(LayoutConstants.TYPE_PORTLET);
355                                    sb.append("')");
356    
357                                    runSQL(sb.toString());
358                            }
359                    }
360                    finally {
361                            EntityCacheUtil.clearCache();
362                            FinderCacheUtil.clearCache();
363                    }
364            }
365    
366            protected void fixUserDefaultRolePermissionsMySQL(
367                            long userClassNameId, long userGroupClassNameId, long[] companyIds)
368                    throws Exception {
369    
370                    for (long companyId : companyIds) {
371                            Role powerUserRole = RoleLocalServiceUtil.getRole(
372                                    companyId, RoleConstants.POWER_USER);
373                            Role userRole = RoleLocalServiceUtil.getRole(
374                                    companyId, RoleConstants.USER);
375    
376                            StringBundler sb = new StringBundler(19);
377    
378                            sb.append("update ignore ResourcePermission inner join Layout on ");
379                            sb.append("ResourcePermission.companyId = Layout.companyId and ");
380                            sb.append("ResourcePermission.primKey like ");
381                            sb.append("replace('[$PLID$]_LAYOUT_%', '[$PLID$]', ");
382                            sb.append("cast_text(Layout.plid)) inner join Group_ on ");
383                            sb.append("Layout.groupId = Group_.groupId set ");
384                            sb.append("ResourcePermission.roleId = ");
385                            sb.append(userRole.getRoleId());
386                            sb.append(" where ResourcePermission.scope = ");
387                            sb.append(ResourceConstants.SCOPE_INDIVIDUAL);
388                            sb.append(" and ResourcePermission.roleId = ");
389                            sb.append(powerUserRole.getRoleId());
390                            sb.append(" and (Group_.classNameId = ");
391                            sb.append(userClassNameId);
392                            sb.append(" or Group_.classNameId = ");
393                            sb.append(userGroupClassNameId);
394                            sb.append(") and Layout.type_ = '");
395                            sb.append(LayoutConstants.TYPE_PORTLET);
396                            sb.append(StringPool.APOSTROPHE);
397    
398                            runSQL(sb.toString());
399                    }
400            }
401    
402            protected void fixUserDefaultRolePermissionsOracle(
403                            long userClassNameId, long userGroupClassNameId, long[] companyIds)
404                    throws Exception {
405    
406                    try {
407                            runSQL("alter table ResourcePermission drop column plid");
408                    }
409                    catch (SQLException sqle) {
410                            if (_log.isDebugEnabled()) {
411                                    _log.debug(sqle, sqle);
412                            }
413                    }
414    
415                    runSQL("alter table ResourcePermission add plid NUMBER null");
416    
417                    runSQL("create index tmp_res_plid on ResourcePermission(plid)");
418    
419                    StringBundler sb = new StringBundler(6);
420    
421                    sb.append("update ResourcePermission r1 set plid = (select ");
422                    sb.append("SUBSTR(ResourcePermission.primKey, 0, ");
423                    sb.append("INSTR(ResourcePermission.primKey, '_LAYOUT_') -1) from ");
424                    sb.append("ResourcePermission where r1.resourcePermissionId = ");
425                    sb.append("ResourcePermission.resourcePermissionId and ");
426                    sb.append("ResourcePermission.primKey like '%_LAYOUT_%')");
427    
428                    runSQL(sb.toString());
429    
430                    for (long companyId : companyIds) {
431                            Role powerUserRole = RoleLocalServiceUtil.getRole(
432                                    companyId, RoleConstants.POWER_USER);
433                            Role userRole = RoleLocalServiceUtil.getRole(
434                                    companyId, RoleConstants.USER);
435    
436                            sb = new StringBundler(24);
437    
438                            sb.append("update ResourcePermission r1 set roleId = ");
439                            sb.append(userRole.getRoleId());
440                            sb.append(" where exists (select ");
441                            sb.append("ResourcePermission.resourcePermissionId from ");
442                            sb.append("ResourcePermission inner join Layout on ");
443                            sb.append("ResourcePermission.plid = Layout.plid inner join ");
444                            sb.append("Group_ on Layout.groupId = Group_.groupId where ");
445                            sb.append("r1.resourcePermissionId = ResourcePermission.");
446                            sb.append("resourcePermissionId and ResourcePermission.scope = ");
447                            sb.append(ResourceConstants.SCOPE_INDIVIDUAL);
448                            sb.append(" and ResourcePermission.roleId = ");
449                            sb.append(powerUserRole.getRoleId());
450                            sb.append(" and (Group_.classNameId = ");
451                            sb.append(userClassNameId);
452                            sb.append(" or Group_.classNameId = ");
453                            sb.append(userGroupClassNameId);
454                            sb.append(") and Layout.type_ = '");
455                            sb.append(LayoutConstants.TYPE_PORTLET);
456                            sb.append("') and not exists (select resourcePermissionId from ");
457                            sb.append("ResourcePermission r2 where r1.name = r2.name and ");
458                            sb.append("r1.scope = r2.scope and r1.primKey = r2.primKey and ");
459                            sb.append("r2.roleId = ");
460                            sb.append(userRole.getRoleId());
461                            sb.append(")");
462    
463                            runSQL(sb.toString());
464                    }
465    
466                    runSQL("alter table ResourcePermission drop column plid");
467            }
468    
469            protected boolean isPrivateLayout(String name, String primKey)
470                    throws PortalException, SystemException {
471    
472                    if (!name.equals(Layout.class.getName()) &&
473                            !primKey.contains(PortletConstants.LAYOUT_SEPARATOR)) {
474    
475                            return false;
476                    }
477    
478                    if (primKey.contains(PortletConstants.LAYOUT_SEPARATOR)) {
479                            primKey = StringUtil.extractFirst(
480                                    primKey, PortletConstants.LAYOUT_SEPARATOR);
481                    }
482    
483                    long plid = GetterUtil.getLong(primKey);
484    
485                    Layout layout = LayoutLocalServiceUtil.getLayout(plid);
486    
487                    if (layout.isPublicLayout() || layout.isTypeControlPanel()) {
488                            return false;
489                    }
490    
491                    return true;
492            }
493    
494            private static final List<String> _DEPRECATED_ORGANIZATION_ACTION_IDS =
495                    new ArrayList<String>();
496    
497            private static Log _log = LogFactoryUtil.getLog(VerifyPermission.class);
498    
499            static {
500                    _DEPRECATED_ORGANIZATION_ACTION_IDS.add(
501                            ActionKeys.MANAGE_ARCHIVED_SETUPS);
502                    _DEPRECATED_ORGANIZATION_ACTION_IDS.add(ActionKeys.MANAGE_LAYOUTS);
503                    _DEPRECATED_ORGANIZATION_ACTION_IDS.add(ActionKeys.MANAGE_STAGING);
504                    _DEPRECATED_ORGANIZATION_ACTION_IDS.add(ActionKeys.MANAGE_TEAMS);
505                    _DEPRECATED_ORGANIZATION_ACTION_IDS.add(ActionKeys.PUBLISH_STAGING);
506                    _DEPRECATED_ORGANIZATION_ACTION_IDS.add("APPROVE_PROPOSAL");
507                    _DEPRECATED_ORGANIZATION_ACTION_IDS.add("ASSIGN_REVIEWER");
508            }
509    
510    }