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