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