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.util.CharPool;
019    import com.liferay.portal.kernel.util.GetterUtil;
020    import com.liferay.portal.kernel.util.KeyValuePair;
021    import com.liferay.portal.kernel.util.PrimitiveLongList;
022    import com.liferay.portal.kernel.util.StringUtil;
023    import com.liferay.portal.kernel.xml.Document;
024    import com.liferay.portal.kernel.xml.Element;
025    import com.liferay.portal.kernel.xml.SAXReaderUtil;
026    import com.liferay.portal.model.Layout;
027    import com.liferay.portal.model.PortletConstants;
028    import com.liferay.portal.model.ResourceConstants;
029    import com.liferay.portal.model.Role;
030    import com.liferay.portal.model.RoleConstants;
031    import com.liferay.portal.model.User;
032    import com.liferay.portal.security.permission.ResourceActionsUtil;
033    import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
034    import com.liferay.portal.service.RoleLocalServiceUtil;
035    import com.liferay.portal.service.permission.PortletPermissionUtil;
036    
037    import java.util.HashMap;
038    import java.util.List;
039    import java.util.Map;
040    import java.util.Set;
041    
042    /**
043     * @author Brian Wing Shun Chan
044     * @author Joel Kozikowski
045     * @author Charles May
046     * @author Raymond Augé
047     * @author Jorge Ferrer
048     * @author Bruno Farache
049     * @author Zsigmond Rab
050     * @author Douglas Wong
051     */
052    public class PermissionExporter {
053    
054            public static final String ROLE_TEAM_PREFIX = "ROLE_TEAM_,*";
055    
056            protected void exportGroupRoles(
057                            LayoutCache layoutCache, long companyId, long groupId,
058                            String resourceName, String entityName, Element parentElement)
059                    throws Exception {
060    
061                    List<Role> roles = layoutCache.getGroupRoles_1to4(groupId);
062    
063                    Element groupElement = exportRoles(
064                            companyId, resourceName, ResourceConstants.SCOPE_GROUP,
065                            String.valueOf(groupId), parentElement, entityName + "-roles",
066                            roles);
067    
068                    if (groupElement.elements().isEmpty()) {
069                            parentElement.remove(groupElement);
070                    }
071            }
072    
073            protected void exportInheritedRoles(
074                            LayoutCache layoutCache, long companyId, long groupId,
075                            String resourceName, String entityName, Element parentElement)
076                    throws Exception {
077    
078                    Element entityRolesElement = SAXReaderUtil.createElement(
079                            entityName + "-roles");
080    
081                    Map<String, Long> entityMap = layoutCache.getEntityMap(
082                            companyId, entityName);
083    
084                    for (Map.Entry<String, Long> entry : entityMap.entrySet()) {
085                            String name = entry.getKey();
086    
087                            long entityGroupId = entry.getValue();
088    
089                            List<Role> entityRoles = layoutCache.getGroupRoles_1to4(
090                                    entityGroupId);
091    
092                            Element entityElement = exportRoles(
093                                    companyId, resourceName, ResourceConstants.SCOPE_GROUP,
094                                    String.valueOf(groupId), entityRolesElement, entityName,
095                                    entityRoles);
096    
097                            if (entityElement.elements().isEmpty()) {
098                                    entityRolesElement.remove(entityElement);
099                            }
100                            else {
101                                    entityElement.addAttribute("name", name);
102                            }
103                    }
104    
105                    if (!entityRolesElement.elements().isEmpty()) {
106                            parentElement.add(entityRolesElement);
107                    }
108            }
109    
110            protected void exportLayoutPermissions(
111                            PortletDataContext portletDataContext, LayoutCache layoutCache,
112                            long companyId, long groupId, Layout layout, Element layoutElement)
113                    throws Exception {
114    
115                    String resourceName = Layout.class.getName();
116                    String resourcePrimKey = String.valueOf(layout.getPlid());
117    
118                    Element permissionsElement = layoutElement.addElement("permissions");
119    
120                    exportPermissions(
121                            layoutCache, companyId, groupId, resourceName, resourcePrimKey,
122                            permissionsElement, false);
123            }
124    
125            protected void exportLayoutRoles(
126                            LayoutCache layoutCache, long companyId, long groupId,
127                            Element rolesElement)
128                    throws Exception {
129    
130                    String resourceName = Layout.class.getName();
131    
132                    exportGroupRoles(
133                            layoutCache, companyId, groupId, resourceName, "community",
134                            rolesElement);
135    
136                    exportUserRoles(
137                            layoutCache, companyId, groupId, resourceName, rolesElement);
138    
139                    exportInheritedRoles(
140                            layoutCache, companyId, groupId, resourceName, "organization",
141                            rolesElement);
142    
143                    exportInheritedRoles(
144                            layoutCache, companyId, groupId, resourceName, "user-group",
145                            rolesElement);
146            }
147    
148            protected void exportPermissions(
149                            LayoutCache layoutCache, long companyId, long groupId,
150                            String resourceName, String resourcePrimKey,
151                            Element permissionsElement, boolean portletActions)
152                    throws Exception {
153    
154                    List<Role> roles = layoutCache.getGroupRoles_5(groupId, resourceName);
155    
156                    List<String> actionIds = null;
157    
158                    if (portletActions) {
159                            actionIds = ResourceActionsUtil.getPortletResourceActions(
160                                    resourceName);
161                    }
162                    else {
163                            actionIds = ResourceActionsUtil.getModelResourceActions(
164                                    resourceName);
165                    }
166    
167                    if (actionIds.isEmpty()) {
168                            return;
169                    }
170    
171                    PrimitiveLongList roleIds = new PrimitiveLongList(roles.size());
172                    Map<Long, Role> roleIdsToRoles = new HashMap<Long, Role>();
173    
174                    for (Role role : roles) {
175                            String name = role.getName();
176    
177                            if (name.equals(RoleConstants.ADMINISTRATOR)) {
178                                    continue;
179                            }
180    
181                            roleIds.add(role.getRoleId());
182                            roleIdsToRoles.put(role.getRoleId(), role);
183                    }
184    
185                    Map<Long, Set<String>> roleIdsToActionIds =
186                            ResourcePermissionLocalServiceUtil.
187                                    getAvailableResourcePermissionActionIds(
188                                            companyId, resourceName, ResourceConstants.SCOPE_INDIVIDUAL,
189                                            resourcePrimKey, roleIds.getArray(), actionIds);
190    
191                    for (Role role : roleIdsToRoles.values()) {
192                            Set<String> availableActionIds = roleIdsToActionIds.get(
193                                    role.getRoleId());
194    
195                            Element roleElement = permissionsElement.addElement("role");
196    
197                            roleElement.addAttribute("name", role.getName());
198                            roleElement.addAttribute("title", role.getTitle());
199                            roleElement.addAttribute("description", role.getDescription());
200                            roleElement.addAttribute("type", String.valueOf(role.getType()));
201                            roleElement.addAttribute("subType", role.getSubtype());
202    
203                            if ((availableActionIds == null) || availableActionIds.isEmpty()) {
204                                    continue;
205                            }
206    
207                            for (String action : availableActionIds) {
208                                    Element actionKeyElement = roleElement.addElement("action-key");
209    
210                                    actionKeyElement.addText(action);
211                            }
212                    }
213            }
214    
215            protected void exportPortletDataPermissions(
216                            PortletDataContext portletDataContext)
217                    throws Exception {
218    
219                    Document document = SAXReaderUtil.createDocument();
220    
221                    Element rootElement = document.addElement("portlet-data-permissions");
222    
223                    Map<String, List<KeyValuePair>> permissionsMap =
224                            portletDataContext.getPermissions();
225    
226                    for (Map.Entry<String, List<KeyValuePair>> entry :
227                                    permissionsMap.entrySet()) {
228    
229                            String[] permissionParts = StringUtil.split(
230                                    entry.getKey(), CharPool.POUND);
231    
232                            String resourceName = permissionParts[0];
233                            long resourcePK = GetterUtil.getLong(permissionParts[1]);
234    
235                            Element portletDataElement = rootElement.addElement("portlet-data");
236    
237                            portletDataElement.addAttribute("resource-name", resourceName);
238                            portletDataElement.addAttribute(
239                                    "resource-pk", String.valueOf(resourcePK));
240    
241                            List<KeyValuePair> permissions = entry.getValue();
242    
243                            for (KeyValuePair permission : permissions) {
244                                    String roleName = permission.getKey();
245                                    String actions = permission.getValue();
246    
247                                    Element permissionsElement = portletDataElement.addElement(
248                                            "permissions");
249    
250                                    permissionsElement.addAttribute("role-name", roleName);
251                                    permissionsElement.addAttribute("actions", actions);
252                            }
253                    }
254    
255                    portletDataContext.addZipEntry(
256                            portletDataContext.getRootPath() + "/portlet-data-permissions.xml",
257                            document.formattedString());
258            }
259    
260            protected void exportPortletPermissions(
261                            PortletDataContext portletDataContext, LayoutCache layoutCache,
262                            String portletId, Layout layout, Element portletElement)
263                    throws Exception {
264    
265                    long companyId = portletDataContext.getCompanyId();
266                    long groupId = portletDataContext.getGroupId();
267    
268                    String resourceName = PortletConstants.getRootPortletId(portletId);
269                    String resourcePrimKey = PortletPermissionUtil.getPrimaryKey(
270                            layout.getPlid(), portletId);
271    
272                    Element permissionsElement = portletElement.addElement("permissions");
273    
274                    exportPermissions(
275                            layoutCache, companyId, groupId, resourceName, resourcePrimKey,
276                            permissionsElement, true);
277            }
278    
279            protected void exportPortletRoles(
280                            LayoutCache layoutCache, long companyId, long groupId,
281                            String portletId, Element rolesElement)
282                    throws Exception {
283    
284                    String resourceName = PortletConstants.getRootPortletId(portletId);
285    
286                    Element portletElement = rolesElement.addElement("portlet");
287    
288                    portletElement.addAttribute("portlet-id", portletId);
289    
290                    exportGroupRoles(
291                            layoutCache, companyId, groupId, resourceName, "community",
292                            portletElement);
293    
294                    exportUserRoles(
295                            layoutCache, companyId, groupId, resourceName, portletElement);
296    
297                    exportInheritedRoles(
298                            layoutCache, companyId, groupId, resourceName, "organization",
299                            portletElement);
300    
301                    exportInheritedRoles(
302                            layoutCache, companyId, groupId, resourceName, "user-group",
303                            portletElement);
304    
305                    if (portletElement.elements().isEmpty()) {
306                            rolesElement.remove(portletElement);
307                    }
308            }
309    
310            protected Element exportRoles(
311                            long companyId, String resourceName, int scope,
312                            String resourcePrimKey, Element parentElement, String elName,
313                            List<Role> roles)
314                    throws Exception {
315    
316                    Element element = parentElement.addElement(elName);
317    
318                    Map<String, List<String>> resourceRoles =
319                            RoleLocalServiceUtil.getResourceRoles(
320                                    companyId, resourceName, scope, resourcePrimKey);
321    
322                    for (Map.Entry<String, List<String>> entry : resourceRoles.entrySet()) {
323                            String roleName = entry.getKey();
324    
325                            if (!hasRole(roles, roleName)) {
326                                    continue;
327                            }
328    
329                            Element roleElement = element.addElement("role");
330    
331                            roleElement.addAttribute("name", roleName);
332    
333                            List<String> actions = entry.getValue();
334    
335                            for (String action : actions) {
336                                    Element actionKeyElement = roleElement.addElement("action-key");
337    
338                                    actionKeyElement.addText(action);
339                                    actionKeyElement.addAttribute("scope", String.valueOf(scope));
340                            }
341                    }
342    
343                    return element;
344            }
345    
346            protected void exportUserRoles(
347                            LayoutCache layoutCache, long companyId, long groupId,
348                            String resourceName, Element parentElement)
349                    throws Exception {
350    
351                    Element userRolesElement = SAXReaderUtil.createElement("user-roles");
352    
353                    List<User> users = layoutCache.getGroupUsers(groupId);
354    
355                    for (User user : users) {
356                            long userId = user.getUserId();
357                            String uuid = user.getUuid();
358    
359                            List<Role> userRoles = layoutCache.getUserRoles(userId);
360    
361                            Element userElement = exportRoles(
362                                    companyId, resourceName, ResourceConstants.SCOPE_GROUP,
363                                    String.valueOf(groupId), userRolesElement, "user", userRoles);
364    
365                            if (userElement.elements().isEmpty()) {
366                                    userRolesElement.remove(userElement);
367                            }
368                            else {
369                                    userElement.addAttribute("uuid", uuid);
370                            }
371                    }
372    
373                    if (!userRolesElement.elements().isEmpty()) {
374                            parentElement.add(userRolesElement);
375                    }
376            }
377    
378            protected boolean hasRole(List<Role> roles, String roleName) {
379                    if ((roles == null) || (roles.size() == 0)) {
380                            return false;
381                    }
382    
383                    for (Role role : roles) {
384                            if (roleName.equals(role.getName())) {
385                                    return true;
386                            }
387                    }
388    
389                    return false;
390            }
391    
392    }