001    /**
002     * Copyright (c) 2000-2010 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.service.impl;
016    
017    import com.liferay.portal.NoSuchResourcePermissionException;
018    import com.liferay.portal.kernel.concurrent.LockRegistry;
019    import com.liferay.portal.kernel.dao.db.DB;
020    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
021    import com.liferay.portal.kernel.exception.PortalException;
022    import com.liferay.portal.kernel.exception.SystemException;
023    import com.liferay.portal.kernel.search.SearchEngineUtil;
024    import com.liferay.portal.kernel.util.StringBundler;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.model.ResourceAction;
027    import com.liferay.portal.model.ResourceConstants;
028    import com.liferay.portal.model.ResourcePermission;
029    import com.liferay.portal.model.ResourcePermissionConstants;
030    import com.liferay.portal.model.Role;
031    import com.liferay.portal.model.RoleConstants;
032    import com.liferay.portal.security.permission.PermissionCacheUtil;
033    import com.liferay.portal.security.permission.ResourceActionsUtil;
034    import com.liferay.portal.service.base.ResourcePermissionLocalServiceBaseImpl;
035    import com.liferay.portal.util.PortalUtil;
036    
037    import java.util.ArrayList;
038    import java.util.Collections;
039    import java.util.List;
040    import java.util.concurrent.locks.Lock;
041    
042    /**
043     * @author Brian Wing Shun Chan
044     * @author Raymond Augé
045     */
046    public class ResourcePermissionLocalServiceImpl
047            extends ResourcePermissionLocalServiceBaseImpl {
048    
049            public void addResourcePermission(
050                            long companyId, String name, int scope, String primKey, long roleId,
051                            String actionId)
052                    throws PortalException, SystemException {
053    
054                    if (scope == ResourceConstants.SCOPE_COMPANY) {
055    
056                            // Remove group permission
057    
058                            removeResourcePermissions(
059                                    companyId, name, ResourceConstants.SCOPE_GROUP, roleId,
060                                    actionId);
061                    }
062                    else if (scope == ResourceConstants.SCOPE_GROUP) {
063    
064                            // Remove company permission
065    
066                            removeResourcePermissions(
067                                    companyId, name, ResourceConstants.SCOPE_COMPANY, roleId,
068                                    actionId);
069                    }
070                    else if (scope == ResourceConstants.SCOPE_INDIVIDUAL) {
071                            throw new NoSuchResourcePermissionException();
072                    }
073    
074                    updateResourcePermission(
075                            companyId, name, scope, primKey, roleId, new String[] {actionId},
076                            ResourcePermissionConstants.OPERATOR_ADD);
077    
078                    PermissionCacheUtil.clearCache();
079            }
080    
081            public List<String> getAvailableResourcePermissionActionIds(
082                            long companyId, String name, int scope, String primKey, long roleId,
083                            List<String> actionIds)
084                    throws PortalException, SystemException {
085    
086                    ResourcePermission resourcePermission =
087                            resourcePermissionPersistence.fetchByC_N_S_P_R(
088                                    companyId, name, scope, primKey, roleId);
089    
090                    if (resourcePermission == null) {
091                            return Collections.EMPTY_LIST;
092                    }
093    
094                    List<String> availableActionIds = new ArrayList<String>(
095                            actionIds.size());
096    
097                    for (String actionId : actionIds) {
098                            ResourceAction resourceAction =
099                                    resourceActionLocalService.getResourceAction(name, actionId);
100    
101                            if (hasActionId(resourcePermission, resourceAction)) {
102                                    availableActionIds.add(actionId);
103                            }
104                    }
105    
106                    return availableActionIds;
107            }
108    
109            public List<ResourcePermission> getResourcePermissions(
110                            long companyId, String name, int scope, String primKey)
111                    throws SystemException {
112    
113                    return resourcePermissionPersistence.findByC_N_S_P(
114                            companyId, name, scope, primKey);
115            }
116    
117            public int getResourcePermissionsCount(
118                            long companyId, String name, int scope, String primKey)
119                    throws SystemException {
120    
121                    return resourcePermissionPersistence.countByC_N_S_P(
122                            companyId, name, scope, primKey);
123            }
124    
125            public List<ResourcePermission> getRoleResourcePermissions(long roleId)
126                    throws SystemException {
127    
128                    return resourcePermissionPersistence.findByRoleId(roleId);
129            }
130    
131            public List<ResourcePermission> getRoleResourcePermissions(
132                            long roleId, int[] scopes, int start, int end)
133                    throws SystemException {
134    
135                    return resourcePermissionFinder.findByR_S(roleId, scopes, start, end);
136            }
137    
138            public boolean hasActionId(
139                    ResourcePermission resourcePermission, ResourceAction resourceAction) {
140    
141                    long actionIds = resourcePermission.getActionIds();
142                    long bitwiseValue = resourceAction.getBitwiseValue();
143    
144                    if ((actionIds & bitwiseValue) == bitwiseValue) {
145                            return true;
146                    }
147                    else {
148                            return false;
149                    }
150            }
151    
152            public boolean hasResourcePermission(
153                            long companyId, String name, int scope, String primKey, long roleId,
154                            String actionId)
155                    throws PortalException, SystemException {
156    
157                    ResourcePermission resourcePermission =
158                            resourcePermissionPersistence.fetchByC_N_S_P_R(
159                                    companyId, name, scope, primKey, roleId);
160    
161                    if (resourcePermission == null) {
162                            return false;
163                    }
164    
165                    ResourceAction resourceAction =
166                            resourceActionLocalService.getResourceAction(name, actionId);
167    
168                    if (hasActionId(resourcePermission, resourceAction)) {
169                            return true;
170                    }
171                    else {
172                            return false;
173                    }
174            }
175    
176            public boolean hasScopeResourcePermission(
177                            long companyId, String name, int scope, long roleId,
178                            String actionId)
179                    throws PortalException, SystemException {
180    
181                    List<ResourcePermission> resourcePermissions =
182                            resourcePermissionPersistence.findByC_N_S(companyId, name, scope);
183    
184                    for (ResourcePermission resourcePermission : resourcePermissions) {
185                            if (hasResourcePermission(
186                                            companyId, name, scope, resourcePermission.getPrimKey(),
187                                            roleId, actionId)) {
188    
189                                    return true;
190                            }
191                    }
192    
193                    return false;
194            }
195    
196            public void mergePermissions(long fromRoleId, long toRoleId)
197                    throws PortalException, SystemException {
198    
199                    Role fromRole = rolePersistence.findByPrimaryKey(fromRoleId);
200                    Role toRole = rolePersistence.findByPrimaryKey(toRoleId);
201    
202                    if (fromRole.getType() != toRole.getType()) {
203                            throw new PortalException("Role types are mismatched");
204                    }
205                    else if (PortalUtil.isSystemRole(toRole.getName())) {
206                            throw new PortalException("Cannot move permissions to system role");
207                    }
208                    else if (PortalUtil.isSystemRole(fromRole.getName())) {
209                            throw new PortalException(
210                                    "Cannot move permissions from system role");
211                    }
212    
213                    List<ResourcePermission> resourcePermissions =
214                            getRoleResourcePermissions(fromRoleId);
215    
216                    for (ResourcePermission resourcePermission : resourcePermissions) {
217                            resourcePermission.setRoleId(toRoleId);
218    
219                            resourcePermissionPersistence.update(resourcePermission, false);
220                    }
221    
222                    roleLocalService.deleteRole(fromRoleId);
223    
224                    PermissionCacheUtil.clearCache();
225            }
226    
227            public void reassignPermissions(long resourcePermissionId, long toRoleId)
228                    throws PortalException, SystemException {
229    
230                    ResourcePermission resourcePermission = getResourcePermission(
231                            resourcePermissionId);
232    
233                    long companyId = resourcePermission.getCompanyId();
234                    String name = resourcePermission.getName();
235                    int scope = resourcePermission.getScope();
236                    String primKey = resourcePermission.getPrimKey();
237                    long fromRoleId = resourcePermission.getRoleId();
238    
239                    Role toRole = roleLocalService.getRole(toRoleId);
240    
241                    List<String> actionIds = null;
242    
243                    if (toRole.getType() == RoleConstants.TYPE_REGULAR) {
244                            actionIds = ResourceActionsUtil.getModelResourceActions(name);
245                    }
246                    else {
247                            actionIds =
248                                    ResourceActionsUtil.getModelResourceCommunityDefaultActions(
249                                            name);
250                    }
251    
252                    setResourcePermissions(
253                            companyId, name, scope, primKey, toRoleId,
254                            actionIds.toArray(new String[actionIds.size()]));
255    
256                    resourcePermissionPersistence.remove(resourcePermissionId);
257    
258                    List<ResourcePermission> resourcePermissions =
259                            getRoleResourcePermissions(fromRoleId);
260    
261                    if (resourcePermissions.isEmpty()) {
262                            roleLocalService.deleteRole(fromRoleId);
263                    }
264            }
265    
266            public void removeResourcePermission(
267                            long companyId, String name, int scope, String primKey, long roleId,
268                            String actionId)
269                    throws PortalException, SystemException {
270    
271                    updateResourcePermission(
272                            companyId, name, scope, primKey, roleId, new String[] {actionId},
273                            ResourcePermissionConstants.OPERATOR_REMOVE);
274    
275                    PermissionCacheUtil.clearCache();
276            }
277    
278            public void removeResourcePermissions(
279                            long companyId, String name, int scope, long roleId,
280                            String actionId)
281                    throws PortalException, SystemException {
282    
283                    List<ResourcePermission> resourcePermissions =
284                            resourcePermissionPersistence.findByC_N_S(companyId, name, scope);
285    
286                    for (ResourcePermission resourcePermission : resourcePermissions) {
287                            updateResourcePermission(
288                                    companyId, name, scope, resourcePermission.getPrimKey(), roleId,
289                                    new String[] {actionId},
290                                    ResourcePermissionConstants.OPERATOR_REMOVE);
291                    }
292    
293                    PermissionCacheUtil.clearCache();
294            }
295    
296            public void setResourcePermissions(
297                            long companyId, String name, int scope, String primKey, long roleId,
298                            String[] actionIds)
299                    throws PortalException, SystemException {
300    
301                    updateResourcePermission(
302                            companyId, name, scope, primKey, roleId, actionIds,
303                            ResourcePermissionConstants.OPERATOR_SET);
304            }
305    
306            protected void doUpdateResourcePermission(
307                            long companyId, String name, int scope, String primKey, long roleId,
308                            String[] actionIds, int operator)
309                    throws PortalException, SystemException {
310    
311                    ResourcePermission resourcePermission =
312                            resourcePermissionPersistence.fetchByC_N_S_P_R(
313                                    companyId, name, scope, primKey, roleId);
314    
315                    long oldActionIds = 0;
316    
317                    if (resourcePermission == null) {
318                            if ((operator == ResourcePermissionConstants.OPERATOR_REMOVE) ||
319                                    (actionIds.length == 0)) {
320    
321                                    return;
322                            }
323    
324                            long resourcePermissionId = counterLocalService.increment(
325                                    ResourcePermission.class.getName());
326    
327                            resourcePermission = resourcePermissionPersistence.create(
328                                    resourcePermissionId);
329    
330                            resourcePermission.setCompanyId(companyId);
331                            resourcePermission.setName(name);
332                            resourcePermission.setScope(scope);
333                            resourcePermission.setPrimKey(primKey);
334                            resourcePermission.setRoleId(roleId);
335                    }
336                    else {
337                            oldActionIds = resourcePermission.getActionIds();
338                    }
339    
340                    long actionIdsLong = resourcePermission.getActionIds();
341    
342                    if (operator == ResourcePermissionConstants.OPERATOR_SET) {
343                            actionIdsLong = 0;
344                    }
345    
346                    for (String actionId : actionIds) {
347                            ResourceAction resourceAction =
348                                    resourceActionLocalService.getResourceAction(name, actionId);
349    
350                            if ((operator == ResourcePermissionConstants.OPERATOR_ADD) ||
351                                    (operator == ResourcePermissionConstants.OPERATOR_SET)) {
352    
353                                    actionIdsLong |= resourceAction.getBitwiseValue();
354                            }
355                            else {
356                                    actionIdsLong =
357                                            actionIdsLong & (~resourceAction.getBitwiseValue());
358                            }
359                    }
360    
361                    if (oldActionIds == actionIdsLong) {
362                            return;
363                    }
364    
365                    if (actionIdsLong == 0) {
366                            resourcePermissionPersistence.remove(resourcePermission);
367                    }
368                    else {
369                            resourcePermission.setActionIds(actionIdsLong);
370    
371                            resourcePermissionPersistence.update(resourcePermission, false);
372                    }
373    
374                    PermissionCacheUtil.clearCache();
375    
376                    SearchEngineUtil.updatePermissionFields(name, primKey);
377            }
378    
379            protected void updateResourcePermission(
380                            long companyId, String name, int scope, String primKey, long roleId,
381                            String[] actionIds, int operator)
382                    throws PortalException, SystemException {
383    
384                    DB db = DBFactoryUtil.getDB();
385    
386                    if (!db.getType().equals(DB.TYPE_HYPERSONIC)) {
387                            doUpdateResourcePermission(
388                                    companyId, name, scope, primKey, roleId, actionIds, operator);
389    
390                            return;
391                    }
392    
393                    StringBundler sb = new StringBundler(9);
394    
395                    sb.append(companyId);
396                    sb.append(StringPool.POUND);
397                    sb.append(name);
398                    sb.append(StringPool.POUND);
399                    sb.append(scope);
400                    sb.append(StringPool.POUND);
401                    sb.append(primKey);
402                    sb.append(StringPool.POUND);
403                    sb.append(roleId);
404    
405                    String groupName = getClass().getName();
406                    String key = sb.toString();
407    
408                    Lock lock = LockRegistry.allocateLock(groupName, key);
409    
410                    lock.lock();
411    
412                    try {
413                            doUpdateResourcePermission(
414                                    companyId, name, scope, primKey, roleId, actionIds, operator);
415                    }
416                    finally {
417                            lock.unlock();
418    
419                            LockRegistry.freeLock(groupName, key);
420                    }
421            }
422    
423    }