1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.service.impl;
16  
17  import com.liferay.portal.NoSuchResourcePermissionException;
18  import com.liferay.portal.kernel.concurrent.LockRegistry;
19  import com.liferay.portal.kernel.dao.db.DB;
20  import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
21  import com.liferay.portal.kernel.exception.PortalException;
22  import com.liferay.portal.kernel.exception.SystemException;
23  import com.liferay.portal.kernel.search.SearchEngineUtil;
24  import com.liferay.portal.kernel.util.StringBundler;
25  import com.liferay.portal.kernel.util.StringPool;
26  import com.liferay.portal.model.ResourceAction;
27  import com.liferay.portal.model.ResourceConstants;
28  import com.liferay.portal.model.ResourcePermission;
29  import com.liferay.portal.model.ResourcePermissionConstants;
30  import com.liferay.portal.model.Role;
31  import com.liferay.portal.model.RoleConstants;
32  import com.liferay.portal.security.permission.PermissionCacheUtil;
33  import com.liferay.portal.security.permission.ResourceActionsUtil;
34  import com.liferay.portal.service.base.ResourcePermissionLocalServiceBaseImpl;
35  import com.liferay.portal.util.PortalUtil;
36  
37  import java.util.ArrayList;
38  import java.util.Collections;
39  import java.util.List;
40  import java.util.concurrent.locks.Lock;
41  
42  /**
43   * <a href="ResourcePermissionLocalServiceImpl.java.html"><b><i>View Source</i>
44   * </b></a>
45   *
46   * @author Brian Wing Shun Chan
47   * @author Raymond Augé
48   */
49  public class ResourcePermissionLocalServiceImpl
50      extends ResourcePermissionLocalServiceBaseImpl {
51  
52      public void addResourcePermission(
53              long companyId, String name, int scope, String primKey, long roleId,
54              String actionId)
55          throws PortalException, SystemException {
56  
57          if (scope == ResourceConstants.SCOPE_COMPANY) {
58  
59              // Remove group permission
60  
61              removeResourcePermissions(
62                  companyId, name, ResourceConstants.SCOPE_GROUP, roleId,
63                  actionId);
64          }
65          else if (scope == ResourceConstants.SCOPE_GROUP) {
66  
67              // Remove company permission
68  
69              removeResourcePermissions(
70                  companyId, name, ResourceConstants.SCOPE_COMPANY, roleId,
71                  actionId);
72          }
73          else if (scope == ResourceConstants.SCOPE_INDIVIDUAL) {
74              throw new NoSuchResourcePermissionException();
75          }
76  
77          updateResourcePermission(
78              companyId, name, scope, primKey, roleId, new String[] {actionId},
79              ResourcePermissionConstants.OPERATOR_ADD);
80  
81          PermissionCacheUtil.clearCache();
82      }
83  
84      public List<String> getAvailableResourcePermissionActionIds(
85              long companyId, String name, int scope, String primKey, long roleId,
86              List<String> actionIds)
87          throws PortalException, SystemException {
88  
89          ResourcePermission resourcePermission =
90              resourcePermissionPersistence.fetchByC_N_S_P_R(
91                  companyId, name, scope, primKey, roleId);
92  
93          if (resourcePermission == null) {
94              return Collections.EMPTY_LIST;
95          }
96  
97          List<String> availableActionIds = new ArrayList<String>(
98              actionIds.size());
99  
100         for (String actionId : actionIds) {
101             ResourceAction resourceAction =
102                 resourceActionLocalService.getResourceAction(name, actionId);
103 
104             if (hasActionId(resourcePermission, resourceAction)) {
105                 availableActionIds.add(actionId);
106             }
107         }
108 
109         return availableActionIds;
110     }
111 
112     public int getResourcePermissionsCount(
113             long companyId, String name, int scope, String primKey)
114         throws SystemException {
115 
116         return resourcePermissionPersistence.countByC_N_S_P(
117             companyId, name, scope, primKey);
118     }
119 
120     public List<ResourcePermission> getRoleResourcePermissions(long roleId)
121         throws SystemException {
122 
123         return resourcePermissionPersistence.findByRoleId(roleId);
124     }
125 
126     public List<ResourcePermission> getRoleResourcePermissions(
127             long roleId, int[] scopes, int start, int end)
128         throws SystemException {
129 
130         return resourcePermissionFinder.findByR_S(roleId, scopes, start, end);
131     }
132 
133     public boolean hasActionId(
134         ResourcePermission resourcePermission, ResourceAction resourceAction) {
135 
136         long actionIds = resourcePermission.getActionIds();
137         long bitwiseValue = resourceAction.getBitwiseValue();
138 
139         if ((actionIds & bitwiseValue) == bitwiseValue) {
140             return true;
141         }
142         else {
143             return false;
144         }
145     }
146 
147     public boolean hasResourcePermission(
148             long companyId, String name, int scope, String primKey, long roleId,
149             String actionId)
150         throws PortalException, SystemException {
151 
152         ResourcePermission resourcePermission =
153             resourcePermissionPersistence.fetchByC_N_S_P_R(
154                 companyId, name, scope, primKey, roleId);
155 
156         if (resourcePermission == null) {
157             return false;
158         }
159 
160         ResourceAction resourceAction =
161             resourceActionLocalService.getResourceAction(name, actionId);
162 
163         if (hasActionId(resourcePermission, resourceAction)) {
164             return true;
165         }
166         else {
167             return false;
168         }
169     }
170 
171     public boolean hasScopeResourcePermission(
172             long companyId, String name, int scope, long roleId,
173             String actionId)
174         throws PortalException, SystemException {
175 
176         List<ResourcePermission> resourcePermissions =
177             resourcePermissionPersistence.findByC_N_S(companyId, name, scope);
178 
179         for (ResourcePermission resourcePermission : resourcePermissions) {
180             if (hasResourcePermission(
181                     companyId, name, scope, resourcePermission.getPrimKey(),
182                     roleId, actionId)) {
183 
184                 return true;
185             }
186         }
187 
188         return false;
189     }
190 
191     public void mergePermissions(long fromRoleId, long toRoleId)
192         throws PortalException, SystemException {
193 
194         Role fromRole = rolePersistence.findByPrimaryKey(fromRoleId);
195         Role toRole = rolePersistence.findByPrimaryKey(toRoleId);
196 
197         if (fromRole.getType() != toRole.getType()) {
198             throw new PortalException("Role types are mismatched");
199         }
200         else if (PortalUtil.isSystemRole(toRole.getName())) {
201             throw new PortalException("Cannot move permissions to system role");
202         }
203         else if (PortalUtil.isSystemRole(fromRole.getName())) {
204             throw new PortalException(
205                 "Cannot move permissions from system role");
206         }
207 
208         List<ResourcePermission> resourcePermissions =
209             getRoleResourcePermissions(fromRoleId);
210 
211         for (ResourcePermission resourcePermission : resourcePermissions) {
212             resourcePermission.setRoleId(toRoleId);
213 
214             resourcePermissionPersistence.update(resourcePermission, false);
215         }
216 
217         roleLocalService.deleteRole(fromRoleId);
218 
219         PermissionCacheUtil.clearCache();
220     }
221 
222     public void reassignPermissions(long resourcePermissionId, long toRoleId)
223         throws PortalException, SystemException {
224 
225         ResourcePermission resourcePermission = getResourcePermission(
226             resourcePermissionId);
227 
228         long companyId = resourcePermission.getCompanyId();
229         String name = resourcePermission.getName();
230         int scope = resourcePermission.getScope();
231         String primKey = resourcePermission.getPrimKey();
232         long fromRoleId = resourcePermission.getRoleId();
233 
234         Role toRole = roleLocalService.getRole(toRoleId);
235 
236         List<String> actionIds = null;
237 
238         if (toRole.getType() == RoleConstants.TYPE_REGULAR) {
239             actionIds = ResourceActionsUtil.getModelResourceActions(name);
240         }
241         else {
242             actionIds =
243                 ResourceActionsUtil.getModelResourceCommunityDefaultActions(
244                     name);
245         }
246 
247         setResourcePermissions(
248             companyId, name, scope, primKey, toRoleId,
249             actionIds.toArray(new String[actionIds.size()]));
250 
251         resourcePermissionPersistence.remove(resourcePermissionId);
252 
253         List<ResourcePermission> resourcePermissions =
254             getRoleResourcePermissions(fromRoleId);
255 
256         if (resourcePermissions.isEmpty()) {
257             roleLocalService.deleteRole(fromRoleId);
258         }
259     }
260 
261     public void removeResourcePermission(
262             long companyId, String name, int scope, String primKey, long roleId,
263             String actionId)
264         throws PortalException, SystemException {
265 
266         updateResourcePermission(
267             companyId, name, scope, primKey, roleId, new String[] {actionId},
268             ResourcePermissionConstants.OPERATOR_REMOVE);
269 
270         PermissionCacheUtil.clearCache();
271     }
272 
273     public void removeResourcePermissions(
274             long companyId, String name, int scope, long roleId,
275             String actionId)
276         throws PortalException, SystemException {
277 
278         List<ResourcePermission> resourcePermissions =
279             resourcePermissionPersistence.findByC_N_S(companyId, name, scope);
280 
281         for (ResourcePermission resourcePermission : resourcePermissions) {
282             updateResourcePermission(
283                 companyId, name, scope, resourcePermission.getPrimKey(), roleId,
284                 new String[] {actionId},
285                 ResourcePermissionConstants.OPERATOR_REMOVE);
286         }
287 
288         PermissionCacheUtil.clearCache();
289     }
290 
291     public void setResourcePermissions(
292             long companyId, String name, int scope, String primKey, long roleId,
293             String[] actionIds)
294         throws PortalException, SystemException {
295 
296         updateResourcePermission(
297             companyId, name, scope, primKey, roleId, actionIds,
298             ResourcePermissionConstants.OPERATOR_SET);
299     }
300 
301     protected void doUpdateResourcePermission(
302             long companyId, String name, int scope, String primKey, long roleId,
303             String[] actionIds, int operator)
304         throws PortalException, SystemException {
305 
306         ResourcePermission resourcePermission =
307             resourcePermissionPersistence.fetchByC_N_S_P_R(
308                 companyId, name, scope, primKey, roleId);
309 
310         if (resourcePermission == null) {
311             if (operator == ResourcePermissionConstants.OPERATOR_REMOVE) {
312                 return;
313             }
314 
315             long resourcePermissionId = counterLocalService.increment(
316                 ResourcePermission.class.getName());
317 
318             resourcePermission = resourcePermissionPersistence.create(
319                 resourcePermissionId);
320 
321             resourcePermission.setCompanyId(companyId);
322             resourcePermission.setName(name);
323             resourcePermission.setScope(scope);
324             resourcePermission.setPrimKey(primKey);
325             resourcePermission.setRoleId(roleId);
326         }
327 
328         long actionIdsLong = resourcePermission.getActionIds();
329 
330         if (operator == ResourcePermissionConstants.OPERATOR_SET) {
331             actionIdsLong = 0;
332         }
333 
334         for (String actionId : actionIds) {
335             ResourceAction resourceAction =
336                 resourceActionLocalService.getResourceAction(name, actionId);
337 
338             if ((operator == ResourcePermissionConstants.OPERATOR_ADD) ||
339                 (operator == ResourcePermissionConstants.OPERATOR_SET)) {
340 
341                 actionIdsLong |= resourceAction.getBitwiseValue();
342             }
343             else {
344                 actionIdsLong =
345                     actionIdsLong & (~resourceAction.getBitwiseValue());
346             }
347         }
348 
349         resourcePermission.setActionIds(actionIdsLong);
350 
351         resourcePermissionPersistence.update(resourcePermission, false);
352 
353         PermissionCacheUtil.clearCache();
354 
355         SearchEngineUtil.updatePermissionFields(name, primKey);
356     }
357 
358     protected void updateResourcePermission(
359             long companyId, String name, int scope, String primKey, long roleId,
360             String[] actionIds, int operator)
361         throws PortalException, SystemException {
362 
363         DB db = DBFactoryUtil.getDB();
364 
365         if (!db.getType().equals(DB.TYPE_HYPERSONIC)) {
366             doUpdateResourcePermission(
367                 companyId, name, scope, primKey, roleId, actionIds, operator);
368 
369             return;
370         }
371 
372         StringBundler sb = new StringBundler(9);
373 
374         sb.append(companyId);
375         sb.append(StringPool.POUND);
376         sb.append(name);
377         sb.append(StringPool.POUND);
378         sb.append(scope);
379         sb.append(StringPool.POUND);
380         sb.append(primKey);
381         sb.append(StringPool.POUND);
382         sb.append(roleId);
383 
384         String groupName = getClass().getName();
385         String key = sb.toString();
386 
387         Lock lock = LockRegistry.allocateLock(groupName, key);
388 
389         lock.lock();
390 
391         try {
392             doUpdateResourcePermission(
393                 companyId, name, scope, primKey, roleId, actionIds, operator);
394         }
395         finally {
396             lock.unlock();
397 
398             LockRegistry.freeLock(groupName, key);
399         }
400     }
401 
402 }