001    /**
002     * Copyright (c) 2000-2011 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 void deleteResourcePermission(long resourcePermissionId)
082                    throws PortalException, SystemException {
083    
084                    resourcePermissionPersistence.remove(resourcePermissionId);
085            }
086    
087            public void deleteResourcePermissions(
088                            long companyId, String name, int scope, long primKey)
089                    throws PortalException, SystemException {
090    
091                    deleteResourcePermissions(
092                            companyId, name, scope, String.valueOf(primKey));
093            }
094    
095            public void deleteResourcePermissions(
096                            long companyId, String name, int scope, String primKey)
097                    throws PortalException, SystemException {
098    
099                    List<ResourcePermission> resourcePermissions =
100                            resourcePermissionPersistence.findByC_N_S_P(
101                                    companyId, name, scope, primKey);
102    
103                    for (ResourcePermission resourcePermission : resourcePermissions) {
104                            deleteResourcePermission(
105                                    resourcePermission.getResourcePermissionId());
106                    }
107            }
108    
109            public List<String> getAvailableResourcePermissionActionIds(
110                            long companyId, String name, int scope, String primKey, long roleId,
111                            List<String> actionIds)
112                    throws PortalException, SystemException {
113    
114                    ResourcePermission resourcePermission =
115                            resourcePermissionPersistence.fetchByC_N_S_P_R(
116                                    companyId, name, scope, primKey, roleId);
117    
118                    if (resourcePermission == null) {
119                            return Collections.EMPTY_LIST;
120                    }
121    
122                    List<String> availableActionIds = new ArrayList<String>(
123                            actionIds.size());
124    
125                    for (String actionId : actionIds) {
126                            ResourceAction resourceAction =
127                                    resourceActionLocalService.getResourceAction(name, actionId);
128    
129                            if (hasActionId(resourcePermission, resourceAction)) {
130                                    availableActionIds.add(actionId);
131                            }
132                    }
133    
134                    return availableActionIds;
135            }
136    
137            public List<ResourcePermission> getResourcePermissions(
138                            long companyId, String name, int scope, String primKey)
139                    throws SystemException {
140    
141                    return resourcePermissionPersistence.findByC_N_S_P(
142                            companyId, name, scope, primKey);
143            }
144    
145            public int getResourcePermissionsCount(
146                            long companyId, String name, int scope, String primKey)
147                    throws SystemException {
148    
149                    return resourcePermissionPersistence.countByC_N_S_P(
150                            companyId, name, scope, primKey);
151            }
152    
153            public List<ResourcePermission> getRoleResourcePermissions(long roleId)
154                    throws SystemException {
155    
156                    return resourcePermissionPersistence.findByRoleId(roleId);
157            }
158    
159            public List<ResourcePermission> getRoleResourcePermissions(
160                            long roleId, int[] scopes, int start, int end)
161                    throws SystemException {
162    
163                    return resourcePermissionFinder.findByR_S(roleId, scopes, start, end);
164            }
165    
166            public boolean hasActionId(
167                    ResourcePermission resourcePermission, ResourceAction resourceAction) {
168    
169                    long actionIds = resourcePermission.getActionIds();
170                    long bitwiseValue = resourceAction.getBitwiseValue();
171    
172                    if ((actionIds & bitwiseValue) == bitwiseValue) {
173                            return true;
174                    }
175                    else {
176                            return false;
177                    }
178            }
179    
180            public boolean hasResourcePermission(
181                            long companyId, String name, int scope, String primKey, long roleId,
182                            String actionId)
183                    throws PortalException, SystemException {
184    
185                    ResourcePermission resourcePermission =
186                            resourcePermissionPersistence.fetchByC_N_S_P_R(
187                                    companyId, name, scope, primKey, roleId);
188    
189                    if (resourcePermission == null) {
190                            return false;
191                    }
192    
193                    ResourceAction resourceAction =
194                            resourceActionLocalService.getResourceAction(name, actionId);
195    
196                    if (hasActionId(resourcePermission, resourceAction)) {
197                            return true;
198                    }
199                    else {
200                            return false;
201                    }
202            }
203    
204            public boolean hasScopeResourcePermission(
205                            long companyId, String name, int scope, long roleId,
206                            String actionId)
207                    throws PortalException, SystemException {
208    
209                    List<ResourcePermission> resourcePermissions =
210                            resourcePermissionPersistence.findByC_N_S(companyId, name, scope);
211    
212                    for (ResourcePermission resourcePermission : resourcePermissions) {
213                            if (hasResourcePermission(
214                                            companyId, name, scope, resourcePermission.getPrimKey(),
215                                            roleId, actionId)) {
216    
217                                    return true;
218                            }
219                    }
220    
221                    return false;
222            }
223    
224            public void mergePermissions(long fromRoleId, long toRoleId)
225                    throws PortalException, SystemException {
226    
227                    Role fromRole = rolePersistence.findByPrimaryKey(fromRoleId);
228                    Role toRole = rolePersistence.findByPrimaryKey(toRoleId);
229    
230                    if (fromRole.getType() != toRole.getType()) {
231                            throw new PortalException("Role types are mismatched");
232                    }
233                    else if (PortalUtil.isSystemRole(toRole.getName())) {
234                            throw new PortalException("Cannot move permissions to system role");
235                    }
236                    else if (PortalUtil.isSystemRole(fromRole.getName())) {
237                            throw new PortalException(
238                                    "Cannot move permissions from system role");
239                    }
240    
241                    List<ResourcePermission> resourcePermissions =
242                            getRoleResourcePermissions(fromRoleId);
243    
244                    for (ResourcePermission resourcePermission : resourcePermissions) {
245                            resourcePermission.setRoleId(toRoleId);
246    
247                            resourcePermissionPersistence.update(resourcePermission, false);
248                    }
249    
250                    roleLocalService.deleteRole(fromRoleId);
251    
252                    PermissionCacheUtil.clearCache();
253            }
254    
255            public void reassignPermissions(long resourcePermissionId, long toRoleId)
256                    throws PortalException, SystemException {
257    
258                    ResourcePermission resourcePermission = getResourcePermission(
259                            resourcePermissionId);
260    
261                    long companyId = resourcePermission.getCompanyId();
262                    String name = resourcePermission.getName();
263                    int scope = resourcePermission.getScope();
264                    String primKey = resourcePermission.getPrimKey();
265                    long fromRoleId = resourcePermission.getRoleId();
266    
267                    Role toRole = roleLocalService.getRole(toRoleId);
268    
269                    List<String> actionIds = null;
270    
271                    if (toRole.getType() == RoleConstants.TYPE_REGULAR) {
272                            actionIds = ResourceActionsUtil.getModelResourceActions(name);
273                    }
274                    else {
275                            actionIds =
276                                    ResourceActionsUtil.getModelResourceCommunityDefaultActions(
277                                            name);
278                    }
279    
280                    setResourcePermissions(
281                            companyId, name, scope, primKey, toRoleId,
282                            actionIds.toArray(new String[actionIds.size()]));
283    
284                    resourcePermissionPersistence.remove(resourcePermissionId);
285    
286                    List<ResourcePermission> resourcePermissions =
287                            getRoleResourcePermissions(fromRoleId);
288    
289                    if (resourcePermissions.isEmpty()) {
290                            roleLocalService.deleteRole(fromRoleId);
291                    }
292            }
293    
294            public void removeResourcePermission(
295                            long companyId, String name, int scope, String primKey, long roleId,
296                            String actionId)
297                    throws PortalException, SystemException {
298    
299                    updateResourcePermission(
300                            companyId, name, scope, primKey, roleId, new String[] {actionId},
301                            ResourcePermissionConstants.OPERATOR_REMOVE);
302    
303                    PermissionCacheUtil.clearCache();
304            }
305    
306            public void removeResourcePermissions(
307                            long companyId, String name, int scope, long roleId,
308                            String actionId)
309                    throws PortalException, SystemException {
310    
311                    List<ResourcePermission> resourcePermissions =
312                            resourcePermissionPersistence.findByC_N_S(companyId, name, scope);
313    
314                    for (ResourcePermission resourcePermission : resourcePermissions) {
315                            updateResourcePermission(
316                                    companyId, name, scope, resourcePermission.getPrimKey(), roleId,
317                                    new String[] {actionId},
318                                    ResourcePermissionConstants.OPERATOR_REMOVE);
319                    }
320    
321                    PermissionCacheUtil.clearCache();
322            }
323    
324            public void setResourcePermissions(
325                            long companyId, String name, int scope, String primKey, long roleId,
326                            String[] actionIds)
327                    throws PortalException, SystemException {
328    
329                    updateResourcePermission(
330                            companyId, name, scope, primKey, roleId, actionIds,
331                            ResourcePermissionConstants.OPERATOR_SET);
332            }
333    
334            protected void doUpdateResourcePermission(
335                            long companyId, String name, int scope, String primKey, long roleId,
336                            String[] actionIds, int operator)
337                    throws PortalException, SystemException {
338    
339                    ResourcePermission resourcePermission =
340                            resourcePermissionPersistence.fetchByC_N_S_P_R(
341                                    companyId, name, scope, primKey, roleId);
342    
343                    long oldActionIds = 0;
344    
345                    if (resourcePermission == null) {
346                            if ((operator == ResourcePermissionConstants.OPERATOR_REMOVE) ||
347                                    (actionIds.length == 0)) {
348    
349                                    return;
350                            }
351    
352                            long resourcePermissionId = counterLocalService.increment(
353                                    ResourcePermission.class.getName());
354    
355                            resourcePermission = resourcePermissionPersistence.create(
356                                    resourcePermissionId);
357    
358                            resourcePermission.setCompanyId(companyId);
359                            resourcePermission.setName(name);
360                            resourcePermission.setScope(scope);
361                            resourcePermission.setPrimKey(primKey);
362                            resourcePermission.setRoleId(roleId);
363                    }
364                    else {
365                            oldActionIds = resourcePermission.getActionIds();
366                    }
367    
368                    long actionIdsLong = resourcePermission.getActionIds();
369    
370                    if (operator == ResourcePermissionConstants.OPERATOR_SET) {
371                            actionIdsLong = 0;
372                    }
373    
374                    for (String actionId : actionIds) {
375                            ResourceAction resourceAction =
376                                    resourceActionLocalService.getResourceAction(name, actionId);
377    
378                            if ((operator == ResourcePermissionConstants.OPERATOR_ADD) ||
379                                    (operator == ResourcePermissionConstants.OPERATOR_SET)) {
380    
381                                    actionIdsLong |= resourceAction.getBitwiseValue();
382                            }
383                            else {
384                                    actionIdsLong =
385                                            actionIdsLong & (~resourceAction.getBitwiseValue());
386                            }
387                    }
388    
389                    if (oldActionIds == actionIdsLong) {
390                            return;
391                    }
392    
393                    if (actionIdsLong == 0) {
394                            resourcePermissionPersistence.remove(resourcePermission);
395                    }
396                    else {
397                            resourcePermission.setActionIds(actionIdsLong);
398    
399                            resourcePermissionPersistence.update(resourcePermission, false);
400                    }
401    
402                    PermissionCacheUtil.clearCache();
403    
404                    SearchEngineUtil.updatePermissionFields(name, primKey);
405            }
406    
407            protected void updateResourcePermission(
408                            long companyId, String name, int scope, String primKey, long roleId,
409                            String[] actionIds, int operator)
410                    throws PortalException, SystemException {
411    
412                    DB db = DBFactoryUtil.getDB();
413    
414                    if (!db.getType().equals(DB.TYPE_HYPERSONIC)) {
415                            doUpdateResourcePermission(
416                                    companyId, name, scope, primKey, roleId, actionIds, operator);
417    
418                            return;
419                    }
420    
421                    StringBundler sb = new StringBundler(9);
422    
423                    sb.append(companyId);
424                    sb.append(StringPool.POUND);
425                    sb.append(name);
426                    sb.append(StringPool.POUND);
427                    sb.append(scope);
428                    sb.append(StringPool.POUND);
429                    sb.append(primKey);
430                    sb.append(StringPool.POUND);
431                    sb.append(roleId);
432    
433                    String groupName = getClass().getName();
434                    String key = sb.toString();
435    
436                    Lock lock = LockRegistry.allocateLock(groupName, key);
437    
438                    lock.lock();
439    
440                    try {
441                            doUpdateResourcePermission(
442                                    companyId, name, scope, primKey, roleId, actionIds, operator);
443                    }
444                    finally {
445                            lock.unlock();
446    
447                            LockRegistry.freeLock(groupName, key);
448                    }
449            }
450    
451    }