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