001    /**
002     * Copyright (c) 2000-2012 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.lar;
016    
017    import com.liferay.portal.kernel.lar.PortletDataContext;
018    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.util.CharPool;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.KeyValuePair;
024    import com.liferay.portal.kernel.util.MapUtil;
025    import com.liferay.portal.kernel.util.PrimitiveLongList;
026    import com.liferay.portal.kernel.util.StringUtil;
027    import com.liferay.portal.kernel.xml.Document;
028    import com.liferay.portal.kernel.xml.Element;
029    import com.liferay.portal.kernel.xml.SAXReaderUtil;
030    import com.liferay.portal.model.Group;
031    import com.liferay.portal.model.GroupConstants;
032    import com.liferay.portal.model.Layout;
033    import com.liferay.portal.model.Permission;
034    import com.liferay.portal.model.PortletConstants;
035    import com.liferay.portal.model.Resource;
036    import com.liferay.portal.model.ResourceConstants;
037    import com.liferay.portal.model.Role;
038    import com.liferay.portal.model.RoleConstants;
039    import com.liferay.portal.model.User;
040    import com.liferay.portal.security.permission.ResourceActionsUtil;
041    import com.liferay.portal.service.GroupLocalServiceUtil;
042    import com.liferay.portal.service.PermissionLocalServiceUtil;
043    import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
044    import com.liferay.portal.service.RoleLocalServiceUtil;
045    import com.liferay.portal.service.permission.PortletPermissionUtil;
046    import com.liferay.portal.util.PropsValues;
047    
048    import java.util.HashMap;
049    import java.util.List;
050    import java.util.Map;
051    import java.util.Set;
052    
053    import org.apache.commons.lang.time.StopWatch;
054    
055    /**
056     * @author Brian Wing Shun Chan
057     * @author Joel Kozikowski
058     * @author Charles May
059     * @author Raymond Augé
060     * @author Jorge Ferrer
061     * @author Bruno Farache
062     * @author Zsigmond Rab
063     * @author Douglas Wong
064     */
065    public class PermissionExporter {
066    
067            public static final String ROLE_TEAM_PREFIX = "ROLE_TEAM_,*";
068    
069            protected Element exportGroupPermissions(
070                            long companyId, long groupId, String resourceName,
071                            String resourcePrimKey, Element parentElement, String elementName)
072                    throws Exception {
073    
074                    Element element = parentElement.addElement(elementName);
075    
076                    List<Permission> permissions =
077                            PermissionLocalServiceUtil.getGroupPermissions(
078                                    groupId, companyId, resourceName,
079                                    ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey);
080    
081                    List<String> actions = ResourceActionsUtil.getActions(permissions);
082    
083                    for (String action : actions) {
084                            Element actionKeyElement = element.addElement("action-key");
085    
086                            actionKeyElement.addText(action);
087                    }
088    
089                    return element;
090            }
091    
092            protected void exportGroupRoles(
093                            LayoutCache layoutCache, long companyId, long groupId,
094                            String resourceName, String entityName, Element parentElement)
095                    throws Exception {
096    
097                    List<Role> roles = layoutCache.getGroupRoles_1to4(groupId);
098    
099                    Element groupElement = exportRoles(
100                            companyId, resourceName, ResourceConstants.SCOPE_GROUP,
101                            String.valueOf(groupId), parentElement, entityName + "-roles",
102                            roles);
103    
104                    if (groupElement.elements().isEmpty()) {
105                            parentElement.remove(groupElement);
106                    }
107            }
108    
109            protected void exportInheritedPermissions(
110                            LayoutCache layoutCache, long companyId, String resourceName,
111                            String resourcePrimKey, Element parentElement, String entityName)
112                    throws Exception {
113    
114                    Element entityPermissionsElement = SAXReaderUtil.createElement(
115                            entityName + "-permissions");
116    
117                    Map<String, Long> entityMap = layoutCache.getEntityMap(
118                            companyId, entityName);
119    
120                    for (Map.Entry<String, Long> entry : entityMap.entrySet()) {
121                            String name = entry.getKey();
122    
123                            long entityGroupId = entry.getValue();
124    
125                            Element entityElement = exportGroupPermissions(
126                                    companyId, entityGroupId, resourceName, resourcePrimKey,
127                                    entityPermissionsElement, entityName + "-actions");
128    
129                            if (entityElement.elements().isEmpty()) {
130                                    entityPermissionsElement.remove(entityElement);
131                            }
132                            else {
133                                    entityElement.addAttribute("name", name);
134                            }
135                    }
136    
137                    if (!entityPermissionsElement.elements().isEmpty()) {
138                            parentElement.add(entityPermissionsElement);
139                    }
140            }
141    
142            protected void exportInheritedRoles(
143                            LayoutCache layoutCache, long companyId, long groupId,
144                            String resourceName, String entityName, Element parentElement)
145                    throws Exception {
146    
147                    Element entityRolesElement = SAXReaderUtil.createElement(
148                            entityName + "-roles");
149    
150                    Map<String, Long> entityMap = layoutCache.getEntityMap(
151                            companyId, entityName);
152    
153                    for (Map.Entry<String, Long> entry : entityMap.entrySet()) {
154                            String name = entry.getKey();
155    
156                            long entityGroupId = entry.getValue();
157    
158                            List<Role> entityRoles = layoutCache.getGroupRoles_1to4(
159                                    entityGroupId);
160    
161                            Element entityElement = exportRoles(
162                                    companyId, resourceName, ResourceConstants.SCOPE_GROUP,
163                                    String.valueOf(groupId), entityRolesElement, entityName,
164                                    entityRoles);
165    
166                            if (entityElement.elements().isEmpty()) {
167                                    entityRolesElement.remove(entityElement);
168                            }
169                            else {
170                                    entityElement.addAttribute("name", name);
171                            }
172                    }
173    
174                    if (!entityRolesElement.elements().isEmpty()) {
175                            parentElement.add(entityRolesElement);
176                    }
177            }
178    
179            protected void exportLayoutPermissions(
180                            PortletDataContext portletDataContext, LayoutCache layoutCache,
181                            long companyId, long groupId, Layout layout, Element layoutElement,
182                            boolean exportUserPermissions)
183                    throws Exception {
184    
185                    String resourceName = Layout.class.getName();
186                    String resourcePrimKey = String.valueOf(layout.getPlid());
187    
188                    Element permissionsElement = layoutElement.addElement("permissions");
189    
190                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
191                            exportPermissions_5(
192                                    layoutCache, companyId, groupId, resourceName, resourcePrimKey,
193                                    permissionsElement, false);
194                    }
195                    else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
196                            exportPermissions_6(
197                                    layoutCache, companyId, groupId, resourceName, resourcePrimKey,
198                                    permissionsElement, false);
199                    }
200                    else {
201                            exportPermissions_1to4(
202                                    layoutCache, companyId, groupId, resourceName, resourcePrimKey,
203                                    permissionsElement, exportUserPermissions);
204                    }
205            }
206    
207            protected void exportLayoutRoles(
208                            LayoutCache layoutCache, long companyId, long groupId,
209                            Element rolesElement)
210                    throws Exception {
211    
212                    String resourceName = Layout.class.getName();
213    
214                    exportGroupRoles(
215                            layoutCache, companyId, groupId, resourceName, "community",
216                            rolesElement);
217    
218                    exportUserRoles(
219                            layoutCache, companyId, groupId, resourceName, rolesElement);
220    
221                    exportInheritedRoles(
222                            layoutCache, companyId, groupId, resourceName, "organization",
223                            rolesElement);
224    
225                    exportInheritedRoles(
226                            layoutCache, companyId, groupId, resourceName, "user-group",
227                            rolesElement);
228            }
229    
230            protected void exportPermissions_1to4(
231                            LayoutCache layoutCache, long companyId, long groupId,
232                            String resourceName, String resourcePrimKey,
233                            Element permissionsElement, boolean exportUserPermissions)
234                    throws Exception {
235    
236                    Group guestGroup = GroupLocalServiceUtil.getGroup(
237                            companyId, GroupConstants.GUEST);
238    
239                    exportGroupPermissions(
240                            companyId, groupId, resourceName, resourcePrimKey,
241                            permissionsElement, "community-actions");
242    
243                    if (groupId != guestGroup.getGroupId()) {
244                            exportGroupPermissions(
245                                    companyId, guestGroup.getGroupId(), resourceName,
246                                    resourcePrimKey, permissionsElement, "guest-actions");
247                    }
248    
249                    if (exportUserPermissions) {
250                            exportUserPermissions(
251                                    layoutCache, companyId, groupId, resourceName, resourcePrimKey,
252                                    permissionsElement);
253                    }
254    
255                    exportInheritedPermissions(
256                            layoutCache, companyId, resourceName, resourcePrimKey,
257                            permissionsElement, "organization");
258    
259                    exportInheritedPermissions(
260                            layoutCache, companyId, resourceName, resourcePrimKey,
261                            permissionsElement, "user-group");
262            }
263    
264            protected void exportPermissions_5(
265                            LayoutCache layoutCache, long companyId, long groupId,
266                            String resourceName, String resourcePrimKey,
267                            Element permissionsElement, boolean portletActions)
268                    throws Exception {
269    
270                    Resource resource = layoutCache.getResource(
271                            companyId, groupId, resourceName,
272                            ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
273                            portletActions);
274    
275                    List<Role> roles = layoutCache.getGroupRoles_5(groupId, resourceName);
276    
277                    for (Role role : roles) {
278                            if (role.getName().equals(RoleConstants.ADMINISTRATOR)) {
279                                    continue;
280                            }
281    
282                            Element roleElement = permissionsElement.addElement("role");
283    
284                            roleElement.addAttribute("name", role.getName());
285                            roleElement.addAttribute("title", role.getTitle());
286                            roleElement.addAttribute("description", role.getDescription());
287                            roleElement.addAttribute("type", String.valueOf(role.getType()));
288    
289                            List<Permission> permissions =
290                                    PermissionLocalServiceUtil.getRolePermissions(
291                                            role.getRoleId(), resource.getResourceId());
292    
293                            List<String> actions = ResourceActionsUtil.getActions(permissions);
294    
295                            for (String action : actions) {
296                                    Element actionKeyElement = roleElement.addElement("action-key");
297    
298                                    actionKeyElement.addText(action);
299                            }
300                    }
301            }
302    
303            protected void exportPermissions_6(
304                            LayoutCache layoutCache, long companyId, long groupId,
305                            String resourceName, String resourcePrimKey,
306                            Element permissionsElement, boolean portletActions)
307                    throws Exception {
308    
309                    List<Role> roles = layoutCache.getGroupRoles_5(groupId, resourceName);
310    
311                    List<String> actionIds = null;
312    
313                    if (portletActions) {
314                            actionIds = ResourceActionsUtil.getPortletResourceActions(
315                                    resourceName);
316                    }
317                    else {
318                            actionIds = ResourceActionsUtil.getModelResourceActions(
319                                    resourceName);
320                    }
321    
322                    if (actionIds.isEmpty()) {
323                            return;
324                    }
325    
326                    PrimitiveLongList roleIds = new PrimitiveLongList(roles.size());
327                    Map<Long, Role> roleIdsToRoles = new HashMap<Long, Role>();
328    
329                    for (Role role : roles) {
330                            String name = role.getName();
331    
332                            if (name.equals(RoleConstants.ADMINISTRATOR)) {
333                                    continue;
334                            }
335    
336                            roleIds.add(role.getRoleId());
337                            roleIdsToRoles.put(role.getRoleId(), role);
338                    }
339    
340                    Map<Long, Set<String>> roleIdsToActionIds =
341                            ResourcePermissionLocalServiceUtil.
342                                    getAvailableResourcePermissionActionIds(
343                                            companyId, resourceName, ResourceConstants.SCOPE_INDIVIDUAL,
344                                            resourcePrimKey, roleIds.getArray(), actionIds);
345    
346                    for (Role role : roleIdsToRoles.values()) {
347                            Set<String> availableActionIds = roleIdsToActionIds.get(
348                                    role.getRoleId());
349    
350                            Element roleElement = permissionsElement.addElement("role");
351    
352                            roleElement.addAttribute("name", role.getName());
353                            roleElement.addAttribute("title", role.getTitle());
354                            roleElement.addAttribute("description", role.getDescription());
355                            roleElement.addAttribute("type", String.valueOf(role.getType()));
356    
357                            if ((availableActionIds == null) || availableActionIds.isEmpty()) {
358                                    continue;
359                            }
360    
361                            for (String action : availableActionIds) {
362                                    Element actionKeyElement = roleElement.addElement("action-key");
363    
364                                    actionKeyElement.addText(action);
365                            }
366                    }
367            }
368    
369            protected void exportPortletDataPermissions(
370                            PortletDataContext portletDataContext)
371                    throws Exception {
372    
373                    Document document = SAXReaderUtil.createDocument();
374    
375                    Element rootElement = document.addElement("portlet-data-permissions");
376    
377                    Map<String, List<KeyValuePair>> permissionsMap =
378                            portletDataContext.getPermissions();
379    
380                    for (Map.Entry<String, List<KeyValuePair>> entry :
381                                    permissionsMap.entrySet()) {
382    
383                            String[] permissionParts = StringUtil.split(
384                                    entry.getKey(), CharPool.POUND);
385    
386                            String resourceName = permissionParts[0];
387                            long resourcePK = GetterUtil.getLong(permissionParts[1]);
388    
389                            Element portletDataElement = rootElement.addElement("portlet-data");
390    
391                            portletDataElement.addAttribute("resource-name", resourceName);
392                            portletDataElement.addAttribute(
393                                    "resource-pk", String.valueOf(resourcePK));
394    
395                            List<KeyValuePair> permissions = entry.getValue();
396    
397                            for (KeyValuePair permission : permissions) {
398                                    String roleName = permission.getKey();
399                                    String actions = permission.getValue();
400    
401                                    Element permissionsElement = portletDataElement.addElement(
402                                            "permissions");
403    
404                                    permissionsElement.addAttribute("role-name", roleName);
405                                    permissionsElement.addAttribute("actions", actions);
406                            }
407                    }
408    
409                    portletDataContext.addZipEntry(
410                            portletDataContext.getRootPath() + "/portlet-data-permissions.xml",
411                            document.formattedString());
412            }
413    
414            protected void exportPortletPermissions(
415                            PortletDataContext portletDataContext, LayoutCache layoutCache,
416                            String portletId, Layout layout, Element portletElement)
417                    throws Exception {
418    
419                    long companyId = portletDataContext.getCompanyId();
420                    long groupId = portletDataContext.getGroupId();
421    
422                    String resourceName = PortletConstants.getRootPortletId(portletId);
423                    String resourcePrimKey = PortletPermissionUtil.getPrimaryKey(
424                            layout.getPlid(), portletId);
425    
426                    Element permissionsElement = portletElement.addElement("permissions");
427    
428                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
429                            exportPermissions_5(
430                                    layoutCache, companyId, groupId, resourceName, resourcePrimKey,
431                                    permissionsElement, true);
432                    }
433                    else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
434                            exportPermissions_6(
435                                    layoutCache, companyId, groupId, resourceName, resourcePrimKey,
436                                    permissionsElement, true);
437                    }
438                    else {
439                            boolean exportUserPermissions = MapUtil.getBoolean(
440                                    portletDataContext.getParameterMap(),
441                                    PortletDataHandlerKeys.USER_PERMISSIONS);
442    
443                            exportPermissions_1to4(
444                                    layoutCache, companyId, groupId, resourceName, resourcePrimKey,
445                                    permissionsElement, exportUserPermissions);
446    
447                            Element rolesElement = portletElement.addElement("roles");
448    
449                            exportPortletRoles(
450                                    layoutCache, companyId, groupId, portletId, rolesElement);
451                    }
452            }
453    
454            protected void exportPortletRoles(
455                            LayoutCache layoutCache, long companyId, long groupId,
456                            String portletId, Element rolesElement)
457                    throws Exception {
458    
459                    String resourceName = PortletConstants.getRootPortletId(portletId);
460    
461                    Element portletElement = rolesElement.addElement("portlet");
462    
463                    portletElement.addAttribute("portlet-id", portletId);
464    
465                    exportGroupRoles(
466                            layoutCache, companyId, groupId, resourceName, "community",
467                            portletElement);
468    
469                    exportUserRoles(
470                            layoutCache, companyId, groupId, resourceName, portletElement);
471    
472                    exportInheritedRoles(
473                            layoutCache, companyId, groupId, resourceName, "organization",
474                            portletElement);
475    
476                    exportInheritedRoles(
477                            layoutCache, companyId, groupId, resourceName, "user-group",
478                            portletElement);
479    
480                    if (portletElement.elements().isEmpty()) {
481                            rolesElement.remove(portletElement);
482                    }
483            }
484    
485            protected Element exportRoles(
486                            long companyId, String resourceName, int scope,
487                            String resourcePrimKey, Element parentElement, String elName,
488                            List<Role> roles)
489                    throws Exception {
490    
491                    Element element = parentElement.addElement(elName);
492    
493                    Map<String, List<String>> resourceRoles =
494                            RoleLocalServiceUtil.getResourceRoles(
495                                    companyId, resourceName, scope, resourcePrimKey);
496    
497                    for (Map.Entry<String, List<String>> entry : resourceRoles.entrySet()) {
498                            String roleName = entry.getKey();
499    
500                            if (!hasRole(roles, roleName)) {
501                                    continue;
502                            }
503    
504                            Element roleElement = element.addElement("role");
505    
506                            roleElement.addAttribute("name", roleName);
507    
508                            List<String> actions = entry.getValue();
509    
510                            for (String action : actions) {
511                                    Element actionKeyElement = roleElement.addElement("action-key");
512    
513                                    actionKeyElement.addText(action);
514                                    actionKeyElement.addAttribute("scope", String.valueOf(scope));
515                            }
516                    }
517    
518                    return element;
519            }
520    
521            protected void exportUserPermissions(
522                            LayoutCache layoutCache, long companyId, long groupId,
523                            String resourceName, String resourcePrimKey, Element parentElement)
524                    throws Exception {
525    
526                    StopWatch stopWatch = null;
527    
528                    if (_log.isDebugEnabled()) {
529                            stopWatch = new StopWatch();
530    
531                            stopWatch.start();
532                    }
533    
534                    Element userPermissionsElement = SAXReaderUtil.createElement(
535                            "user-permissions");
536    
537                    List<User> users = layoutCache.getGroupUsers(groupId);
538    
539                    for (User user : users) {
540                            String uuid = user.getUuid();
541    
542                            Element userActionsElement = SAXReaderUtil.createElement(
543                                    "user-actions");
544    
545                            List<Permission> permissions =
546                                    PermissionLocalServiceUtil.getUserPermissions(
547                                            user.getUserId(), companyId, resourceName,
548                                            ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey);
549    
550                            List<String> actions = ResourceActionsUtil.getActions(permissions);
551    
552                            for (String action : actions) {
553                                    Element actionKeyElement = userActionsElement.addElement(
554                                            "action-key");
555    
556                                    actionKeyElement.addText(action);
557                            }
558    
559                            if (!userActionsElement.elements().isEmpty()) {
560                                    userActionsElement.addAttribute("uuid", uuid);
561                                    userPermissionsElement.add(userActionsElement);
562                            }
563                    }
564    
565                    if (!userPermissionsElement.elements().isEmpty()) {
566                            parentElement.add(userPermissionsElement);
567                    }
568    
569                    if (_log.isDebugEnabled()) {
570                            _log.debug(
571                                    "Export user permissions for {" + resourceName + ", " +
572                                            resourcePrimKey + "} with " + users.size() +
573                                                    " users takes " + stopWatch.getTime() + " ms");
574                    }
575            }
576    
577            protected void exportUserRoles(
578                            LayoutCache layoutCache, long companyId, long groupId,
579                            String resourceName, Element parentElement)
580                    throws Exception {
581    
582                    Element userRolesElement = SAXReaderUtil.createElement("user-roles");
583    
584                    List<User> users = layoutCache.getGroupUsers(groupId);
585    
586                    for (User user : users) {
587                            long userId = user.getUserId();
588                            String uuid = user.getUuid();
589    
590                            List<Role> userRoles = layoutCache.getUserRoles(userId);
591    
592                            Element userElement = exportRoles(
593                                    companyId, resourceName, ResourceConstants.SCOPE_GROUP,
594                                    String.valueOf(groupId), userRolesElement, "user", userRoles);
595    
596                            if (userElement.elements().isEmpty()) {
597                                    userRolesElement.remove(userElement);
598                            }
599                            else {
600                                    userElement.addAttribute("uuid", uuid);
601                            }
602                    }
603    
604                    if (!userRolesElement.elements().isEmpty()) {
605                            parentElement.add(userRolesElement);
606                    }
607            }
608    
609            protected boolean hasRole(List<Role> roles, String roleName) {
610                    if ((roles == null) || (roles.size() == 0)) {
611                            return false;
612                    }
613    
614                    for (Role role : roles) {
615                            if (roleName.equals(role.getName())) {
616                                    return true;
617                            }
618                    }
619    
620                    return false;
621            }
622    
623            private static Log _log = LogFactoryUtil.getLog(PermissionExporter.class);
624    
625    }