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