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("description", role.getDescription());
286                            roleElement.addAttribute("type", String.valueOf(role.getType()));
287    
288                            List<Permission> permissions =
289                                    PermissionLocalServiceUtil.getRolePermissions(
290                                            role.getRoleId(), resource.getResourceId());
291    
292                            List<String> actions = ResourceActionsUtil.getActions(permissions);
293    
294                            for (String action : actions) {
295                                    Element actionKeyElement = roleElement.addElement("action-key");
296    
297                                    actionKeyElement.addText(action);
298                            }
299                    }
300            }
301    
302            protected void exportPermissions_6(
303                            LayoutCache layoutCache, long companyId, long groupId,
304                            String resourceName, String resourcePrimKey,
305                            Element permissionsElement, boolean portletActions)
306                    throws Exception {
307    
308                    List<Role> roles = layoutCache.getGroupRoles_5(groupId, resourceName);
309    
310                    List<String> actionIds = null;
311    
312                    if (portletActions) {
313                            actionIds = ResourceActionsUtil.getPortletResourceActions(
314                                    resourceName);
315                    }
316                    else {
317                            actionIds = ResourceActionsUtil.getModelResourceActions(
318                                    resourceName);
319                    }
320    
321                    if (actionIds.isEmpty()) {
322                            return;
323                    }
324    
325                    PrimitiveLongList roleIds = new PrimitiveLongList(roles.size());
326                    Map<Long, Role> roleIdsToRoles = new HashMap<Long, Role>();
327    
328                    for (Role role : roles) {
329                            String name = role.getName();
330    
331                            if (name.equals(RoleConstants.ADMINISTRATOR)) {
332                                    continue;
333                            }
334    
335                            roleIds.add(role.getRoleId());
336                            roleIdsToRoles.put(role.getRoleId(), role);
337                    }
338    
339                    Map<Long, Set<String>> roleIdsToActionIds =
340                            ResourcePermissionLocalServiceUtil.
341                                    getAvailableResourcePermissionActionIds(
342                                            companyId, resourceName, ResourceConstants.SCOPE_INDIVIDUAL,
343                                            resourcePrimKey, roleIds.getArray(), actionIds);
344    
345                    for (Role role : roleIdsToRoles.values()) {
346                            Set<String> availableActionIds = roleIdsToActionIds.get(
347                                    role.getRoleId());
348    
349                            Element roleElement = permissionsElement.addElement("role");
350    
351                            roleElement.addAttribute("name", role.getName());
352                            roleElement.addAttribute("description", role.getDescription());
353                            roleElement.addAttribute("type", String.valueOf(role.getType()));
354    
355                            if ((availableActionIds == null) || availableActionIds.isEmpty()) {
356                                    continue;
357                            }
358    
359                            for (String action : availableActionIds) {
360                                    Element actionKeyElement = roleElement.addElement("action-key");
361    
362                                    actionKeyElement.addText(action);
363                            }
364                    }
365            }
366    
367            protected void exportPortletDataPermissions(
368                            PortletDataContext portletDataContext)
369                    throws Exception {
370    
371                    Document document = SAXReaderUtil.createDocument();
372    
373                    Element rootElement = document.addElement("portlet-data-permissions");
374    
375                    Map<String, List<KeyValuePair>> permissionsMap =
376                            portletDataContext.getPermissions();
377    
378                    for (Map.Entry<String, List<KeyValuePair>> entry :
379                                    permissionsMap.entrySet()) {
380    
381                            String[] permissionParts = StringUtil.split(
382                                    entry.getKey(), CharPool.POUND);
383    
384                            String resourceName = permissionParts[0];
385                            long resourcePK = GetterUtil.getLong(permissionParts[1]);
386    
387                            Element portletDataElement = rootElement.addElement("portlet-data");
388    
389                            portletDataElement.addAttribute("resource-name", resourceName);
390                            portletDataElement.addAttribute(
391                                    "resource-pk", String.valueOf(resourcePK));
392    
393                            List<KeyValuePair> permissions = entry.getValue();
394    
395                            for (KeyValuePair permission : permissions) {
396                                    String roleName = permission.getKey();
397                                    String actions = permission.getValue();
398    
399                                    Element permissionsElement = portletDataElement.addElement(
400                                            "permissions");
401    
402                                    permissionsElement.addAttribute("role-name", roleName);
403                                    permissionsElement.addAttribute("actions", actions);
404                            }
405                    }
406    
407                    portletDataContext.addZipEntry(
408                            portletDataContext.getRootPath() + "/portlet-data-permissions.xml",
409                            document.formattedString());
410            }
411    
412            protected void exportPortletPermissions(
413                            PortletDataContext portletDataContext, LayoutCache layoutCache,
414                            String portletId, Layout layout, Element portletElement)
415                    throws Exception {
416    
417                    long companyId = portletDataContext.getCompanyId();
418                    long groupId = portletDataContext.getGroupId();
419    
420                    String resourceName = PortletConstants.getRootPortletId(portletId);
421                    String resourcePrimKey = PortletPermissionUtil.getPrimaryKey(
422                            layout.getPlid(), portletId);
423    
424                    Element permissionsElement = portletElement.addElement("permissions");
425    
426                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
427                            exportPermissions_5(
428                                    layoutCache, companyId, groupId, resourceName, resourcePrimKey,
429                                    permissionsElement, true);
430                    }
431                    else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
432                            exportPermissions_6(
433                                    layoutCache, companyId, groupId, resourceName, resourcePrimKey,
434                                    permissionsElement, true);
435                    }
436                    else {
437                            boolean exportUserPermissions = MapUtil.getBoolean(
438                                    portletDataContext.getParameterMap(),
439                                    PortletDataHandlerKeys.USER_PERMISSIONS);
440    
441                            exportPermissions_1to4(
442                                    layoutCache, companyId, groupId, resourceName, resourcePrimKey,
443                                    permissionsElement, exportUserPermissions);
444    
445                            Element rolesElement = portletElement.addElement("roles");
446    
447                            exportPortletRoles(
448                                    layoutCache, companyId, groupId, portletId, rolesElement);
449                    }
450            }
451    
452            protected void exportPortletRoles(
453                            LayoutCache layoutCache, long companyId, long groupId,
454                            String portletId, Element rolesElement)
455                    throws Exception {
456    
457                    String resourceName = PortletConstants.getRootPortletId(portletId);
458    
459                    Element portletElement = rolesElement.addElement("portlet");
460    
461                    portletElement.addAttribute("portlet-id", portletId);
462    
463                    exportGroupRoles(
464                            layoutCache, companyId, groupId, resourceName, "community",
465                            portletElement);
466    
467                    exportUserRoles(
468                            layoutCache, companyId, groupId, resourceName, portletElement);
469    
470                    exportInheritedRoles(
471                            layoutCache, companyId, groupId, resourceName, "organization",
472                            portletElement);
473    
474                    exportInheritedRoles(
475                            layoutCache, companyId, groupId, resourceName, "user-group",
476                            portletElement);
477    
478                    if (portletElement.elements().isEmpty()) {
479                            rolesElement.remove(portletElement);
480                    }
481            }
482    
483            protected Element exportRoles(
484                            long companyId, String resourceName, int scope,
485                            String resourcePrimKey, Element parentElement, String elName,
486                            List<Role> roles)
487                    throws Exception {
488    
489                    Element element = parentElement.addElement(elName);
490    
491                    Map<String, List<String>> resourceRoles =
492                            RoleLocalServiceUtil.getResourceRoles(
493                                    companyId, resourceName, scope, resourcePrimKey);
494    
495                    for (Map.Entry<String, List<String>> entry : resourceRoles.entrySet()) {
496                            String roleName = entry.getKey();
497    
498                            if (!hasRole(roles, roleName)) {
499                                    continue;
500                            }
501    
502                            Element roleElement = element.addElement("role");
503    
504                            roleElement.addAttribute("name", roleName);
505    
506                            List<String> actions = entry.getValue();
507    
508                            for (String action : actions) {
509                                    Element actionKeyElement = roleElement.addElement("action-key");
510    
511                                    actionKeyElement.addText(action);
512                                    actionKeyElement.addAttribute("scope", String.valueOf(scope));
513                            }
514                    }
515    
516                    return element;
517            }
518    
519            protected void exportUserPermissions(
520                            LayoutCache layoutCache, long companyId, long groupId,
521                            String resourceName, String resourcePrimKey, Element parentElement)
522                    throws Exception {
523    
524                    StopWatch stopWatch = null;
525    
526                    if (_log.isDebugEnabled()) {
527                            stopWatch = new StopWatch();
528    
529                            stopWatch.start();
530                    }
531    
532                    Element userPermissionsElement = SAXReaderUtil.createElement(
533                            "user-permissions");
534    
535                    List<User> users = layoutCache.getGroupUsers(groupId);
536    
537                    for (User user : users) {
538                            String uuid = user.getUuid();
539    
540                            Element userActionsElement = SAXReaderUtil.createElement(
541                                    "user-actions");
542    
543                            List<Permission> permissions =
544                                    PermissionLocalServiceUtil.getUserPermissions(
545                                            user.getUserId(), companyId, resourceName,
546                                            ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey);
547    
548                            List<String> actions = ResourceActionsUtil.getActions(permissions);
549    
550                            for (String action : actions) {
551                                    Element actionKeyElement = userActionsElement.addElement(
552                                            "action-key");
553    
554                                    actionKeyElement.addText(action);
555                            }
556    
557                            if (!userActionsElement.elements().isEmpty()) {
558                                    userActionsElement.addAttribute("uuid", uuid);
559                                    userPermissionsElement.add(userActionsElement);
560                            }
561                    }
562    
563                    if (!userPermissionsElement.elements().isEmpty()) {
564                            parentElement.add(userPermissionsElement);
565                    }
566    
567                    if (_log.isDebugEnabled()) {
568                            _log.debug(
569                                    "Export user permissions for {" + resourceName + ", " +
570                                            resourcePrimKey + "} with " + users.size() +
571                                                    " users takes " + stopWatch.getTime() + " ms");
572                    }
573            }
574    
575            protected void exportUserRoles(
576                            LayoutCache layoutCache, long companyId, long groupId,
577                            String resourceName, Element parentElement)
578                    throws Exception {
579    
580                    Element userRolesElement = SAXReaderUtil.createElement("user-roles");
581    
582                    List<User> users = layoutCache.getGroupUsers(groupId);
583    
584                    for (User user : users) {
585                            long userId = user.getUserId();
586                            String uuid = user.getUuid();
587    
588                            List<Role> userRoles = layoutCache.getUserRoles(userId);
589    
590                            Element userElement = exportRoles(
591                                    companyId, resourceName, ResourceConstants.SCOPE_GROUP,
592                                    String.valueOf(groupId), userRolesElement, "user", userRoles);
593    
594                            if (userElement.elements().isEmpty()) {
595                                    userRolesElement.remove(userElement);
596                            }
597                            else {
598                                    userElement.addAttribute("uuid", uuid);
599                            }
600                    }
601    
602                    if (!userRolesElement.elements().isEmpty()) {
603                            parentElement.add(userRolesElement);
604                    }
605            }
606    
607            protected boolean hasRole(List<Role> roles, String roleName) {
608                    if ((roles == null) || (roles.size() == 0)) {
609                            return false;
610                    }
611    
612                    for (Role role : roles) {
613                            if (roleName.equals(role.getName())) {
614                                    return true;
615                            }
616                    }
617    
618                    return false;
619            }
620    
621            private static Log _log = LogFactoryUtil.getLog(PermissionExporter.class);
622    
623    }