001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.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                            if ((availableActionIds == null) || availableActionIds.isEmpty()) {
350                                    continue;
351                            }
352    
353                            Element roleElement = permissionsElement.addElement("role");
354    
355                            roleElement.addAttribute("name", role.getName());
356                            roleElement.addAttribute("description", role.getDescription());
357                            roleElement.addAttribute("type", String.valueOf(role.getType()));
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(
374                            "portlet-data-permissions");
375    
376                    Map<String, List<KeyValuePair>> permissionsMap =
377                            portletDataContext.getPermissions();
378    
379                    for (Map.Entry<String, List<KeyValuePair>> entry :
380                                    permissionsMap.entrySet()) {
381    
382                            String[] permissionParts = StringUtil.split(
383                                    entry.getKey(), CharPool.POUND);
384    
385                            String resourceName = permissionParts[0];
386                            long resourcePK = GetterUtil.getLong(permissionParts[1]);
387    
388                            Element portletDataElement = rootElement.addElement(
389                                    "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(
460                            portletId);
461    
462                    Element portletElement = rolesElement.addElement("portlet");
463    
464                    portletElement.addAttribute("portlet-id", portletId);
465    
466                    exportGroupRoles(
467                            layoutCache, companyId, groupId, resourceName, "community",
468                            portletElement);
469    
470                    exportUserRoles(
471                            layoutCache, companyId, groupId, resourceName, portletElement);
472    
473                    exportInheritedRoles(
474                            layoutCache, companyId, groupId, resourceName, "organization",
475                            portletElement);
476    
477                    exportInheritedRoles(
478                            layoutCache, companyId, groupId, resourceName, "user-group",
479                            portletElement);
480    
481                    if (portletElement.elements().isEmpty()) {
482                            rolesElement.remove(portletElement);
483                    }
484            }
485    
486            protected Element exportRoles(
487                            long companyId, String resourceName, int scope,
488                            String resourcePrimKey, Element parentElement, String elName,
489                            List<Role> roles)
490                    throws Exception {
491    
492                    Element element = parentElement.addElement(elName);
493    
494                    Map<String, List<String>> resourceRoles =
495                            RoleLocalServiceUtil.getResourceRoles(
496                                    companyId, resourceName, scope, resourcePrimKey);
497    
498                    for (Map.Entry<String, List<String>> entry : resourceRoles.entrySet()) {
499                            String roleName = entry.getKey();
500    
501                            if (!hasRole(roles, roleName)) {
502                                    continue;
503                            }
504    
505                            Element roleElement = element.addElement("role");
506    
507                            roleElement.addAttribute("name", roleName);
508    
509                            List<String> actions = entry.getValue();
510    
511                            for (String action : actions) {
512                                    Element actionKeyElement = roleElement.addElement("action-key");
513    
514                                    actionKeyElement.addText(action);
515                                    actionKeyElement.addAttribute("scope", String.valueOf(scope));
516                            }
517                    }
518    
519                    return element;
520            }
521    
522            protected void exportUserPermissions(
523                            LayoutCache layoutCache, long companyId, long groupId,
524                            String resourceName, String resourcePrimKey, Element parentElement)
525                    throws Exception {
526    
527                    StopWatch stopWatch = null;
528    
529                    if (_log.isDebugEnabled()) {
530                            stopWatch = new StopWatch();
531    
532                            stopWatch.start();
533                    }
534    
535                    Element userPermissionsElement = SAXReaderUtil.createElement(
536                            "user-permissions");
537    
538                    List<User> users = layoutCache.getGroupUsers(groupId);
539    
540                    for (User user : users) {
541                            String uuid = user.getUuid();
542    
543                            Element userActionsElement = SAXReaderUtil.createElement(
544                                    "user-actions");
545    
546                            List<Permission> permissions =
547                                    PermissionLocalServiceUtil.getUserPermissions(
548                                            user.getUserId(), companyId, resourceName,
549                                            ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey);
550    
551                            List<String> actions = ResourceActionsUtil.getActions(permissions);
552    
553                            for (String action : actions) {
554                                    Element actionKeyElement = userActionsElement.addElement(
555                                            "action-key");
556    
557                                    actionKeyElement.addText(action);
558                            }
559    
560                            if (!userActionsElement.elements().isEmpty()) {
561                                    userActionsElement.addAttribute("uuid", uuid);
562                                    userPermissionsElement.add(userActionsElement);
563                            }
564                    }
565    
566                    if (!userPermissionsElement.elements().isEmpty()) {
567                            parentElement.add(userPermissionsElement);
568                    }
569    
570                    if (_log.isDebugEnabled()) {
571                            _log.debug(
572                                    "Export user permissions for {" + resourceName + ", " +
573                                            resourcePrimKey + "} with " + users.size() +
574                                                    " users takes " + stopWatch.getTime() + " ms");
575                    }
576            }
577    
578            protected void exportUserRoles(
579                            LayoutCache layoutCache, long companyId, long groupId,
580                            String resourceName, Element parentElement)
581                    throws Exception {
582    
583                    Element userRolesElement = SAXReaderUtil.createElement("user-roles");
584    
585                    List<User> users = layoutCache.getGroupUsers(groupId);
586    
587                    for (User user : users) {
588                            long userId = user.getUserId();
589                            String uuid = user.getUuid();
590    
591                            List<Role> userRoles = layoutCache.getUserRoles(userId);
592    
593                            Element userElement = exportRoles(
594                                    companyId, resourceName, ResourceConstants.SCOPE_GROUP,
595                                    String.valueOf(groupId), userRolesElement, "user", userRoles);
596    
597                            if (userElement.elements().isEmpty()) {
598                                    userRolesElement.remove(userElement);
599                            }
600                            else {
601                                    userElement.addAttribute("uuid", uuid);
602                            }
603                    }
604    
605                    if (!userRolesElement.elements().isEmpty()) {
606                            parentElement.add(userRolesElement);
607                    }
608            }
609    
610            protected boolean hasRole(List<Role> roles, String roleName) {
611                    if ((roles == null) || (roles.size() == 0)) {
612                            return false;
613                    }
614    
615                    for (Role role : roles) {
616                            if (roleName.equals(role.getName())) {
617                                    return true;
618                            }
619                    }
620    
621                    return false;
622            }
623    
624            private static Log _log = LogFactoryUtil.getLog(PermissionExporter.class);
625    
626    }