001    /**
002     * Copyright (c) 2000-present 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.NoSuchRoleException;
018    import com.liferay.portal.ResourceActionsException;
019    import com.liferay.portal.kernel.bean.BeanPropertiesUtil;
020    import com.liferay.portal.kernel.exception.PortalException;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.search.SearchEngineUtil;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.ListUtil;
026    import com.liferay.portal.model.AuditedModel;
027    import com.liferay.portal.model.GroupedModel;
028    import com.liferay.portal.model.PermissionedModel;
029    import com.liferay.portal.model.Resource;
030    import com.liferay.portal.model.ResourceConstants;
031    import com.liferay.portal.model.ResourcePermission;
032    import com.liferay.portal.model.Role;
033    import com.liferay.portal.model.RoleConstants;
034    import com.liferay.portal.model.impl.ResourceImpl;
035    import com.liferay.portal.security.permission.PermissionCacheUtil;
036    import com.liferay.portal.security.permission.PermissionThreadLocal;
037    import com.liferay.portal.security.permission.ResourceActionsUtil;
038    import com.liferay.portal.service.ServiceContext;
039    import com.liferay.portal.service.base.ResourceLocalServiceBaseImpl;
040    import com.liferay.portal.service.permission.ModelPermissions;
041    import com.liferay.portal.service.permission.ModelPermissionsFactory;
042    import com.liferay.portal.util.ResourcePermissionsThreadLocal;
043    
044    import java.util.Arrays;
045    import java.util.Iterator;
046    import java.util.List;
047    
048    import org.apache.commons.lang.time.StopWatch;
049    
050    /**
051     * Provides the local service for accessing, adding, and updating resources.
052     *
053     * <p>
054     * Permissions in Liferay are defined for resource/action pairs. Some resources,
055     * known as portlet resources, define actions that the end-user can perform with
056     * respect to a portlet window. Other resources, known as model resources,
057     * define actions that the end-user can perform with respect to the
058     * service/persistence layer.
059     * </p>
060     *
061     * <p>
062     * On creating an entity instance, you should create resources for it. The
063     * following example demonstrates adding resources for an instance of a model
064     * entity named <code>SomeWidget</code>. The IDs of the actions permitted for
065     * the group and guests are passed in from the service context.
066     * </p>
067     *
068     * <p>
069     * <pre>
070     * <code>
071     * resourceLocalService.addModelResources(
072     *              SomeWidget.getCompanyId(), SomeWidget.getGroupId(), userId,
073     *              SomeWidget.class.getName(), SomeWidget.getPrimaryKey(),
074     *              serviceContext.getGroupPermissions, serviceContext.getGuestPermissions);
075     * </code>
076     * </pre>
077     * </p>
078     *
079     * <p>
080     * Just prior to deleting an entity instance, you should delete its resource at
081     * the individual scope. The following example demonstrates deleting a resource
082     * associated with the <code>SomeWidget</code> model entity at the scope
083     * individual scope.
084     * </p>
085     *
086     * <p>
087     * <pre>
088     * <code>
089     * resourceLocalService.deleteResource(
090     *              SomeWidget.getCompanyId(), SomeWidget.class.getName(),
091     *              ResourceConstants.SCOPE_INDIVIDUAL, SomeWidget.getPrimaryKey());
092     * </code>
093     * </pre>
094     * </p>
095     *
096     * @author Brian Wing Shun Chan
097     * @author Wilson S. Man
098     * @author Raymond Aug??
099     * @author Julio Camarero
100     * @author Connor McKay
101     */
102    public class ResourceLocalServiceImpl extends ResourceLocalServiceBaseImpl {
103    
104            /**
105             * Adds resources for the model, always creating a resource at the
106             * individual scope and only creating resources at the group, group
107             * template, and company scope if such resources don't already exist.
108             *
109             * <ol>
110             * <li>
111             * If the service context specifies that default group or default guest
112             * permissions are to be added, then only default permissions are added. See
113             * {@link ServiceContext#setAddGroupPermissions(
114             * boolean)} and {@link
115             * ServiceContext#setAddGuestPermissions(
116             * boolean)}.
117             * </li>
118             * <li>
119             * Else ...
120             * <ol>
121             * <li>
122             * If the service context specifies to derive default permissions, then
123             * default group and guest permissions are derived from the model and
124             * added. See {@link
125             * ServiceContext#setDeriveDefaultPermissions(
126             * boolean)}.
127             * </li>
128             * <li>
129             * Lastly group and guest permissions from the service
130             * context are applied. See {@link
131             * ServiceContext#setGroupPermissions(String[])}
132             * and {@link
133             * ServiceContext#setGuestPermissions(String[])}.
134             * </li>
135             * </ol>
136             *
137             * </li>
138             * </ol>
139             *
140             * @param  auditedModel the model to associate with the resources
141             * @param  serviceContext the service context to apply. Can set whether to
142             *         add the model's default group and guest permissions, set whether
143             *         to derive default group and guest permissions from the model, set
144             *         group permissions to apply, and set guest permissions to apply.
145             * @throws PortalException if no portal actions could be found associated
146             *         with the model or if a portal exception occurred
147             */
148            @Override
149            public void addModelResources(
150                            AuditedModel auditedModel, ServiceContext serviceContext)
151                    throws PortalException {
152    
153                    ModelPermissions modelPermissions =
154                            serviceContext.getModelPermissions();
155    
156                    if ((modelPermissions != null) && !modelPermissions.isEmpty()) {
157                            addModelResources(
158                                    auditedModel.getCompanyId(), getGroupId(auditedModel),
159                                    auditedModel.getUserId(), auditedModel.getModelClassName(),
160                                    String.valueOf(auditedModel.getPrimaryKeyObj()),
161                                    modelPermissions, getPermissionedModel(auditedModel));
162                    }
163                    else if (serviceContext.isAddGroupPermissions() ||
164                                     serviceContext.isAddGuestPermissions()) {
165    
166                            addResources(
167                                    auditedModel.getCompanyId(), getGroupId(auditedModel),
168                                    auditedModel.getUserId(), auditedModel.getModelClassName(),
169                                    String.valueOf(auditedModel.getPrimaryKeyObj()), false,
170                                    serviceContext.isAddGroupPermissions(),
171                                    serviceContext.isAddGuestPermissions(),
172                                    getPermissionedModel(auditedModel));
173                    }
174                    else {
175                            if (serviceContext.isDeriveDefaultPermissions()) {
176                                    serviceContext.deriveDefaultPermissions(
177                                            getGroupId(auditedModel), auditedModel.getModelClassName());
178                            }
179    
180                            addModelResources(
181                                    auditedModel.getCompanyId(), getGroupId(auditedModel),
182                                    auditedModel.getUserId(), auditedModel.getModelClassName(),
183                                    String.valueOf(auditedModel.getPrimaryKeyObj()),
184                                    serviceContext.getModelPermissions(),
185                                    getPermissionedModel(auditedModel));
186                    }
187            }
188    
189            @Override
190            public void addModelResources(
191                            long companyId, long groupId, long userId, String name,
192                            long primKey, ModelPermissions modelPermissions)
193                    throws PortalException {
194    
195                    addModelResources(
196                            companyId, groupId, userId, name, String.valueOf(primKey),
197                            modelPermissions, null);
198            }
199    
200            /**
201             * Adds resources for the model with the name and primary key, always
202             * creating a resource at the individual scope and only creating resources
203             * at the group, group template, and company scope if such resources don't
204             * already exist.
205             *
206             * @param  companyId the primary key of the portal instance
207             * @param  groupId the primary key of the group
208             * @param  userId the primary key of the user adding the resources
209             * @param  name a name for the resource, typically the model's class name
210             * @param  primKey the primary key of the model instance, optionally
211             *         <code>0</code> if no instance exists
212             * @param  groupPermissions the group permissions to be applied
213             * @param  guestPermissions the guest permissions to be applied
214             * @throws PortalException if no portal actions could be found associated
215             *         with the model or if a portal exception occurred
216             */
217            @Override
218            public void addModelResources(
219                            long companyId, long groupId, long userId, String name,
220                            long primKey, String[] groupPermissions, String[] guestPermissions)
221                    throws PortalException {
222    
223                    addModelResources(
224                            companyId, groupId, userId, name, String.valueOf(primKey),
225                            groupPermissions, guestPermissions, null);
226            }
227    
228            @Override
229            public void addModelResources(
230                            long companyId, long groupId, long userId, String name,
231                            String primKey, ModelPermissions modelPermissions)
232                    throws PortalException {
233    
234                    addModelResources(
235                            companyId, groupId, userId, name, primKey, modelPermissions, null);
236            }
237    
238            /**
239             * Adds resources for the model with the name and primary key string, always
240             * creating a resource at the individual scope and only creating resources
241             * at the group, group template, and company scope if such resources don't
242             * already exist.
243             *
244             * @param  companyId the primary key of the portal instance
245             * @param  groupId the primary key of the group
246             * @param  userId the primary key of the user adding the resources
247             * @param  name a name for the resource, typically the model's class name
248             * @param  primKey the primary key string of the model instance, optionally
249             *         an empty string if no instance exists
250             * @param  groupPermissions the group permissions to be applied
251             * @param  guestPermissions the guest permissions to be applied
252             * @throws PortalException if no portal actions could be found associated
253             *         with the model or if a portal exception occurred
254             */
255            @Override
256            public void addModelResources(
257                            long companyId, long groupId, long userId, String name,
258                            String primKey, String[] groupPermissions,
259                            String[] guestPermissions)
260                    throws PortalException {
261    
262                    addModelResources(
263                            companyId, groupId, userId, name, primKey, groupPermissions,
264                            guestPermissions, null);
265            }
266    
267            /**
268             * Adds resources for the entity with the name and primary key, always
269             * creating a resource at the individual scope and only creating resources
270             * at the group, group template, and company scope if such resources don't
271             * already exist.
272             *
273             * @param  companyId the primary key of the portal instance
274             * @param  groupId the primary key of the group
275             * @param  userId the primary key of the user adding the resources
276             * @param  name a name for the resource, which should be a portlet ID if the
277             *         resource is a portlet or the resource's class name otherwise
278             * @param  primKey the primary key of the resource instance, optionally
279             *         <code>0</code> if no instance exists
280             * @param  portletActions whether to associate portlet actions with the
281             *         resource
282             * @param  addGroupPermissions whether to add group permissions
283             * @param  addGuestPermissions whether to add guest permissions
284             * @throws PortalException if no portal actions could be found associated
285             *         with the resource or if a portal exception occurred
286             */
287            @Override
288            public void addResources(
289                            long companyId, long groupId, long userId, String name,
290                            long primKey, boolean portletActions, boolean addGroupPermissions,
291                            boolean addGuestPermissions)
292                    throws PortalException {
293    
294                    addResources(
295                            companyId, groupId, userId, name, String.valueOf(primKey),
296                            portletActions, addGroupPermissions, addGuestPermissions, null);
297            }
298    
299            /**
300             * Adds resources for the entity with the name and primary key string,
301             * always creating a resource at the individual scope and only creating
302             * resources at the group, group template, and company scope if such
303             * resources don't already exist.
304             *
305             * @param  companyId the primary key of the portal instance
306             * @param  groupId the primary key of the group
307             * @param  userId the primary key of the user adding the resources
308             * @param  name a name for the resource, which should be a portlet ID if the
309             *         resource is a portlet or the resource's class name otherwise
310             * @param  primKey the primary key string of the resource instance,
311             *         optionally an empty string if no instance exists
312             * @param  portletActions whether to associate portlet actions with the
313             *         resource
314             * @param  addGroupPermissions whether to add group permissions
315             * @param  addGuestPermissions whether to add guest permissions
316             * @throws PortalException if no portal actions could be found associated
317             *         with the resource or if a portal exception occurred
318             */
319            @Override
320            public void addResources(
321                            long companyId, long groupId, long userId, String name,
322                            String primKey, boolean portletActions, boolean addGroupPermissions,
323                            boolean addGuestPermissions)
324                    throws PortalException {
325    
326                    addResources(
327                            companyId, groupId, userId, name, primKey, portletActions,
328                            addGroupPermissions, addGuestPermissions, null);
329            }
330    
331            /**
332             * Adds resources for the entity with the name. Use this method if the user
333             * is unknown or irrelevant and there is no current entity instance.
334             *
335             * @param  companyId the primary key of the portal instance
336             * @param  groupId the primary key of the group
337             * @param  name a name for the resource, which should be a portlet ID if the
338             *         resource is a portlet or the resource's class name otherwise
339             * @param  portletActions whether to associate portlet actions with the
340             *         resource
341             * @throws PortalException if no portal actions could be found associated
342             *         with the resource or if a portal exception occurred
343             */
344            @Override
345            public void addResources(
346                            long companyId, long groupId, String name, boolean portletActions)
347                    throws PortalException {
348    
349                    addResources(
350                            companyId, groupId, 0, name, null, portletActions, false, false);
351            }
352    
353            /**
354             * Deletes the resource associated with the model at the scope.
355             *
356             * @param  auditedModel the model associated with the resource
357             * @param  scope the scope of the resource. For more information see {@link
358             *         ResourceConstants}.
359             * @throws PortalException if a portal exception occurred
360             */
361            @Override
362            public void deleteResource(AuditedModel auditedModel, int scope)
363                    throws PortalException {
364    
365                    deleteResource(
366                            auditedModel.getCompanyId(), auditedModel.getModelClassName(),
367                            scope, String.valueOf(auditedModel.getPrimaryKeyObj()),
368                            getPermissionedModel(auditedModel));
369            }
370    
371            /**
372             * Deletes the resource matching the primary key at the scope.
373             *
374             * @param  companyId the primary key of the portal instance
375             * @param  name the resource's name, which should be a portlet ID if the
376             *         resource is a portlet or the resource's class name otherwise
377             * @param  scope the scope of the resource. For more information see {@link
378             *         ResourceConstants}.
379             * @param  primKey the primary key of the resource instance
380             * @throws PortalException if a portal exception occurred
381             */
382            @Override
383            public void deleteResource(
384                            long companyId, String name, int scope, long primKey)
385                    throws PortalException {
386    
387                    deleteResource(companyId, name, scope, String.valueOf(primKey), null);
388            }
389    
390            /**
391             * Deletes the resource matching the primary key at the scope.
392             *
393             * @param  companyId the primary key of the portal instance
394             * @param  name the resource's name, which should be a portlet ID if the
395             *         resource is a portlet or the resource's class name otherwise
396             * @param  scope the scope of the resource. For more information see {@link
397             *         ResourceConstants}.
398             * @param  primKey the primary key string of the resource instance
399             * @throws PortalException if a portal exception occurred
400             */
401            @Override
402            public void deleteResource(
403                            long companyId, String name, int scope, String primKey)
404                    throws PortalException {
405    
406                    deleteResource(companyId, name, scope, primKey, null);
407            }
408    
409            /**
410             * Returns a new resource with the name and primary key at the scope.
411             *
412             * @param  companyId the primary key of the portal instance
413             * @param  name a name for the resource, which should be a portlet ID if the
414             *         resource is a portlet or the resource's class name otherwise
415             * @param  scope the scope of the resource. For more information see {@link
416             *         ResourceConstants}.
417             * @param  primKey the primary key string of the resource
418             * @return the new resource
419             */
420            @Override
421            public Resource getResource(
422                    long companyId, String name, int scope, String primKey) {
423    
424                    Resource resource = new ResourceImpl();
425    
426                    resource.setCompanyId(companyId);
427                    resource.setName(name);
428                    resource.setScope(scope);
429                    resource.setPrimKey(primKey);
430    
431                    return resource;
432            }
433    
434            /**
435             * Returns <code>true</code> if the roles have permission to perform the
436             * action on the resources.
437             *
438             * @param  userId the primary key of the user performing the permission
439             *         check
440             * @param  resourceId the primary key of the resource, typically the scope
441             *         group ID representing the scope in which the permission check is
442             *         being performed
443             * @param  resources the resources for which permissions are to be checked
444             * @param  actionId the primary key of the action to be performed on the
445             *         resources
446             * @param  roleIds the primary keys of the roles
447             * @return <code>true</code> if the roles have permission to perform the
448             *         action on the resources;<code>false</code> otherwise
449             * @throws PortalException if any one of the roles with the primary keys
450             *         could not be found or if a resource action with the action ID
451             *         could not be found
452             */
453            @Override
454            public boolean hasUserPermissions(
455                            long userId, long resourceId, List<Resource> resources,
456                            String actionId, long[] roleIds)
457                    throws PortalException {
458    
459                    StopWatch stopWatch = new StopWatch();
460    
461                    stopWatch.start();
462    
463                    int block = 1;
464    
465                    boolean hasUserPermissions =
466                            resourcePermissionLocalService.hasResourcePermission(
467                                    resources, roleIds, actionId);
468    
469                    logHasUserPermissions(userId, resourceId, actionId, stopWatch, block++);
470    
471                    return hasUserPermissions;
472            }
473    
474            /**
475             * Updates the resources for the model, replacing their group and guest
476             * permissions with new ones from the service context.
477             *
478             * @param  auditedModel the model associated with the resources
479             * @param  serviceContext the service context to be applied. Can set group
480             *         and guest permissions.
481             * @throws PortalException if a portal exception occurred
482             */
483            @Override
484            public void updateModelResources(
485                            AuditedModel auditedModel, ServiceContext serviceContext)
486                    throws PortalException {
487    
488                    updateResources(
489                            auditedModel.getCompanyId(), getGroupId(auditedModel),
490                            auditedModel.getModelClassName(),
491                            String.valueOf(auditedModel.getPrimaryKeyObj()),
492                            serviceContext.getModelPermissions(),
493                            getPermissionedModel(auditedModel));
494            }
495    
496            /**
497             * Updates resources matching the group, name, and primary key at the
498             * individual scope, setting new permissions.
499             *
500             * @param  companyId the primary key of the portal instance
501             * @param  groupId the primary key of the group
502             * @param  name the resource's name, which should be a portlet ID if the
503             *         resource is a portlet or the resource's class name otherwise
504             * @param  primKey the primary key of the resource instance
505             * @param  modelPermissions the model permissions to be applied
506             * @throws PortalException if a portal exception occurred
507             */
508            @Override
509            public void updateResources(
510                            long companyId, long groupId, String name, long primKey,
511                            ModelPermissions modelPermissions)
512                    throws PortalException {
513    
514                    updateResources(
515                            companyId, groupId, name, String.valueOf(primKey), modelPermissions,
516                            null);
517            }
518    
519            /**
520             * Updates resources matching the group, name, and primary key at the
521             * individual scope, setting new group and guest permissions.
522             *
523             * @param  companyId the primary key of the portal instance
524             * @param  groupId the primary key of the group
525             * @param  name the resource's name, which should be a portlet ID if the
526             *         resource is a portlet or the resource's class name otherwise
527             * @param  primKey the primary key of the resource instance
528             * @param  groupPermissions the group permissions to be applied
529             * @param  guestPermissions the guest permissions to be applied
530             * @throws PortalException if a portal exception occurred
531             */
532            @Override
533            public void updateResources(
534                            long companyId, long groupId, String name, long primKey,
535                            String[] groupPermissions, String[] guestPermissions)
536                    throws PortalException {
537    
538                    updateResources(
539                            companyId, groupId, name, String.valueOf(primKey), groupPermissions,
540                            guestPermissions, null);
541            }
542    
543            /**
544             * Updates resources matching the group, name, and primary key string at the
545             * individual scope, setting new permissions.
546             *
547             * @param  companyId the primary key of the portal instance
548             * @param  groupId the primary key of the group
549             * @param  name the resource's name, which should be a portlet ID if the
550             *         resource is a portlet or the resource's class name otherwise
551             * @param  primKey the primary key string of the resource instance
552             * @param  modelPermissions the model permissions to be applied
553             * @throws PortalException if a portal exception occurred
554             */
555            @Override
556            public void updateResources(
557                            long companyId, long groupId, String name, String primKey,
558                            ModelPermissions modelPermissions)
559                    throws PortalException {
560    
561                    updateResources(
562                            companyId, groupId, name, primKey, modelPermissions, null);
563            }
564    
565            /**
566             * Updates resources matching the group, name, and primary key string at the
567             * individual scope, setting new group and guest permissions.
568             *
569             * @param  companyId the primary key of the portal instance
570             * @param  groupId the primary key of the group
571             * @param  name the resource's name, which should be a portlet ID if the
572             *         resource is a portlet or the resource's class name otherwise
573             * @param  primKey the primary key string of the resource instance
574             * @param  groupPermissions the group permissions to be applied
575             * @param  guestPermissions the guest permissions to be applied
576             * @throws PortalException if a portal exception occurred
577             */
578            @Override
579            public void updateResources(
580                            long companyId, long groupId, String name, String primKey,
581                            String[] groupPermissions, String[] guestPermissions)
582                    throws PortalException {
583    
584                    ModelPermissions modelPermissions = ModelPermissionsFactory.create(
585                            groupPermissions, guestPermissions);
586    
587                    updateResources(
588                            companyId, groupId, name, primKey, modelPermissions, null);
589            }
590    
591            /**
592             * Updates resources matching the name, primary key string and scope,
593             * replacing the primary key of their resource permissions with the new
594             * primary key.
595             *
596             * @param companyId the primary key of the portal instance
597             * @param name the resource's name, which should be a portlet ID if the
598             *        resource is a portlet or the resource's class name otherwise
599             * @param scope the scope of the resource. For more information see {@link
600             *        ResourceConstants}.
601             * @param primKey the primary key string of the resource instance
602             * @param newPrimKey the new primary key string of the resource
603             */
604            @Override
605            public void updateResources(
606                    long companyId, String name, int scope, String primKey,
607                    String newPrimKey) {
608    
609                    if (resourceBlockLocalService.isSupported(name)) {
610    
611                            // Assuming that this method is used when the primary key of an
612                            // existing record is changed, then nothing needs to happen here, as
613                            // it should still have its resource block ID.
614    
615                    }
616                    else {
617                            updateResourcePermissions(
618                                    companyId, name, scope, primKey, newPrimKey);
619                    }
620            }
621    
622            protected void addGroupPermissions(
623                            long companyId, long groupId, long userId, String name,
624                            Resource resource, boolean portletActions,
625                            PermissionedModel permissionedModel)
626                    throws PortalException {
627    
628                    List<String> actions = null;
629    
630                    if (portletActions) {
631                            actions = ResourceActionsUtil.getPortletResourceGroupDefaultActions(
632                                    name);
633                    }
634                    else {
635                            actions = ResourceActionsUtil.getModelResourceGroupDefaultActions(
636                                    name);
637                    }
638    
639                    String[] actionIds = actions.toArray(new String[actions.size()]);
640    
641                    if (resourceBlockLocalService.isSupported(name)) {
642                            addGroupPermissionsBlocks(
643                                    groupId, resource, actions, permissionedModel);
644                    }
645                    else {
646                            addGroupPermissions(groupId, resource, actionIds);
647                    }
648            }
649    
650            protected void addGroupPermissions(
651                            long groupId, Resource resource, String[] actionIds)
652                    throws PortalException {
653    
654                    Role role = roleLocalService.getDefaultGroupRole(groupId);
655    
656                    resourcePermissionLocalService.setResourcePermissions(
657                            resource.getCompanyId(), resource.getName(), resource.getScope(),
658                            resource.getPrimKey(), role.getRoleId(), actionIds);
659            }
660    
661            protected void addGroupPermissionsBlocks(
662                            long groupId, Resource resource, List<String> actionIds,
663                            PermissionedModel permissionedModel)
664                    throws PortalException {
665    
666                    if (permissionedModel == null) {
667                            throw new IllegalArgumentException("Permissioned model is null");
668                    }
669    
670                    // Scope is assumed to always be individual
671    
672                    Role role = roleLocalService.getDefaultGroupRole(groupId);
673    
674                    resourceBlockLocalService.setIndividualScopePermissions(
675                            resource.getCompanyId(), groupId, resource.getName(),
676                            permissionedModel, role.getRoleId(), actionIds);
677            }
678    
679            protected void addGuestPermissions(
680                            long companyId, long groupId, long userId, String name,
681                            Resource resource, boolean portletActions,
682                            PermissionedModel permissionedModel)
683                    throws PortalException {
684    
685                    List<String> actions = null;
686    
687                    if (portletActions) {
688                            actions = ResourceActionsUtil.getPortletResourceGuestDefaultActions(
689                                    name);
690                    }
691                    else {
692                            actions = ResourceActionsUtil.getModelResourceGuestDefaultActions(
693                                    name);
694                    }
695    
696                    String[] actionIds = actions.toArray(new String[actions.size()]);
697    
698                    if (resourceBlockLocalService.isSupported(name)) {
699                            addGuestPermissionsBlocks(
700                                    companyId, groupId, resource, actions, permissionedModel);
701                    }
702                    else {
703                            addGuestPermissions(companyId, resource, actionIds);
704                    }
705            }
706    
707            protected void addGuestPermissions(
708                            long companyId, Resource resource, String[] actionIds)
709                    throws PortalException {
710    
711                    Role guestRole = roleLocalService.getRole(
712                            companyId, RoleConstants.GUEST);
713    
714                    resourcePermissionLocalService.setResourcePermissions(
715                            resource.getCompanyId(), resource.getName(), resource.getScope(),
716                            resource.getPrimKey(), guestRole.getRoleId(), actionIds);
717            }
718    
719            protected void addGuestPermissionsBlocks(
720                            long companyId, long groupId, Resource resource,
721                            List<String> actionIds, PermissionedModel permissionedModel)
722                    throws PortalException {
723    
724                    if (permissionedModel == null) {
725                            throw new IllegalArgumentException("Permissioned model is null");
726                    }
727    
728                    // Scope is assumed to always be individual
729    
730                    Role guestRole = roleLocalService.getRole(
731                            companyId, RoleConstants.GUEST);
732    
733                    resourceBlockLocalService.setIndividualScopePermissions(
734                            resource.getCompanyId(), groupId, resource.getName(),
735                            permissionedModel, guestRole.getRoleId(), actionIds);
736            }
737    
738            protected void addModelResources(
739                            long companyId, long groupId, long userId, Resource resource,
740                            ModelPermissions modelPermissions,
741                            PermissionedModel permissionedModel)
742                    throws PortalException {
743    
744                    // Owner permissions
745    
746                    Role ownerRole = roleLocalService.getRole(
747                            companyId, RoleConstants.OWNER);
748    
749                    List<String> ownerActionIds =
750                            ResourceActionsUtil.getModelResourceActions(resource.getName());
751    
752                    ownerActionIds = ListUtil.copy(ownerActionIds);
753    
754                    filterOwnerActions(resource.getName(), ownerActionIds);
755    
756                    String[] ownerPermissions = ownerActionIds.toArray(
757                            new String[ownerActionIds.size()]);
758    
759                    if (resourceBlockLocalService.isSupported(resource.getName())) {
760                            if (permissionedModel == null) {
761                                    throw new IllegalArgumentException(
762                                            "Permissioned model is null");
763                            }
764    
765                            // Scope is assumed to always be individual
766    
767                            resourceBlockLocalService.setIndividualScopePermissions(
768                                    resource.getCompanyId(), groupId, resource.getName(),
769                                    permissionedModel, ownerRole.getRoleId(), ownerActionIds);
770    
771                            if (modelPermissions != null) {
772                                    for (String roleName : modelPermissions.getRoleNames()) {
773                                            Role role = getRole(
774                                                    resource.getCompanyId(), groupId, roleName);
775    
776                                            resourceBlockLocalService.setIndividualScopePermissions(
777                                                    resource.getCompanyId(), groupId, resource.getName(),
778                                                    permissionedModel, role.getRoleId(),
779                                                    modelPermissions.getActionIdsList(roleName));
780                                    }
781                            }
782                    }
783                    else {
784                            resourcePermissionLocalService.setOwnerResourcePermissions(
785                                    resource.getCompanyId(), resource.getName(),
786                                    resource.getScope(), resource.getPrimKey(),
787                                    ownerRole.getRoleId(), userId, ownerPermissions);
788    
789                            if (modelPermissions != null) {
790                                    for (String roleName : modelPermissions.getRoleNames()) {
791                                            Role role = getRole(
792                                                    resource.getCompanyId(), groupId, roleName);
793    
794                                            resourcePermissionLocalService.setResourcePermissions(
795                                                    resource.getCompanyId(), resource.getName(),
796                                                    resource.getScope(), resource.getPrimKey(),
797                                                    role.getRoleId(),
798                                                    modelPermissions.getActionIds(roleName));
799                                    }
800                            }
801                    }
802            }
803    
804            protected void addModelResources(
805                            long companyId, long groupId, long userId, Resource resource,
806                            String[] groupPermissions, String[] guestPermissions,
807                            PermissionedModel permissionedModel)
808                    throws PortalException {
809    
810                    ModelPermissions modelPermissions = ModelPermissionsFactory.create(
811                            groupPermissions, guestPermissions);
812    
813                    addModelResources(
814                            companyId, groupId, userId, resource, modelPermissions,
815                            permissionedModel);
816            }
817    
818            protected void addModelResources(
819                            long companyId, long groupId, long userId, String name,
820                            String primKey, ModelPermissions modelPermissions,
821                            PermissionedModel permissionedModel)
822                    throws PortalException {
823    
824                    if (!PermissionThreadLocal.isAddResource()) {
825                            return;
826                    }
827    
828                    validate(name, false);
829    
830                    if (primKey == null) {
831                            return;
832                    }
833    
834                    // Individual
835    
836                    Resource resource = getResource(
837                            companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
838    
839                    // Permissions
840    
841                    boolean flushResourceBlockEnabled =
842                            PermissionThreadLocal.isFlushResourceBlockEnabled(
843                                    companyId, groupId, name);
844                    boolean flushResourcePermissionEnabled =
845                            PermissionThreadLocal.isFlushResourcePermissionEnabled(
846                                    name, primKey);
847    
848                    PermissionThreadLocal.setFlushResourceBlockEnabled(
849                            companyId, groupId, name, false);
850                    PermissionThreadLocal.setFlushResourcePermissionEnabled(
851                            name, primKey, false);
852    
853                    try {
854                            addModelResources(
855                                    companyId, groupId, userId, resource, modelPermissions,
856                                    permissionedModel);
857                    }
858                    finally {
859                            PermissionThreadLocal.setFlushResourceBlockEnabled(
860                                    companyId, groupId, name, flushResourceBlockEnabled);
861                            PermissionThreadLocal.setFlushResourcePermissionEnabled(
862                                    name, primKey, flushResourcePermissionEnabled);
863    
864                            PermissionCacheUtil.clearResourceBlockCache(
865                                    companyId, groupId, name);
866                            PermissionCacheUtil.clearResourcePermissionCache(
867                                    ResourceConstants.SCOPE_INDIVIDUAL, name, primKey);
868    
869                            SearchEngineUtil.updatePermissionFields(name, primKey);
870                    }
871            }
872    
873            protected void addModelResources(
874                            long companyId, long groupId, long userId, String name,
875                            String primKey, String[] groupPermissions,
876                            String[] guestPermissions, PermissionedModel permissionedModel)
877                    throws PortalException {
878    
879                    ModelPermissions modelPermissions = ModelPermissionsFactory.create(
880                            groupPermissions, guestPermissions);
881    
882                    addModelResources(
883                            companyId, groupId, userId, name, primKey, modelPermissions,
884                            permissionedModel);
885            }
886    
887            protected void addResources(
888                            long companyId, long groupId, long userId, Resource resource,
889                            boolean portletActions, PermissionedModel permissionedModel)
890                    throws PortalException {
891    
892                    List<String> actionIds = null;
893    
894                    if (portletActions) {
895                            actionIds = ResourceActionsUtil.getPortletResourceActions(
896                                    resource.getName());
897                    }
898                    else {
899                            actionIds = ResourceActionsUtil.getModelResourceActions(
900                                    resource.getName());
901    
902                            actionIds = ListUtil.copy(actionIds);
903    
904                            filterOwnerActions(resource.getName(), actionIds);
905                    }
906    
907                    Role role = roleLocalService.getRole(companyId, RoleConstants.OWNER);
908    
909                    if (resourceBlockLocalService.isSupported(resource.getName())) {
910                            if (permissionedModel == null) {
911                                    throw new IllegalArgumentException(
912                                            "Permissioned model is null");
913                            }
914    
915                            // Scope is assumed to always be individual
916    
917                            resourceBlockLocalService.setIndividualScopePermissions(
918                                    resource.getCompanyId(), groupId, resource.getName(),
919                                    permissionedModel, role.getRoleId(), actionIds);
920                    }
921                    else {
922                            resourcePermissionLocalService.setOwnerResourcePermissions(
923                                    resource.getCompanyId(), resource.getName(),
924                                    resource.getScope(), resource.getPrimKey(), role.getRoleId(),
925                                    userId, actionIds.toArray(new String[actionIds.size()]));
926                    }
927            }
928    
929            protected void addResources(
930                            long companyId, long groupId, long userId, String name,
931                            String primKey, boolean portletActions, boolean addGroupPermissions,
932                            boolean addGuestPermissions, PermissionedModel permissionedModel)
933                    throws PortalException {
934    
935                    if (!PermissionThreadLocal.isAddResource()) {
936                            return;
937                    }
938    
939                    validate(name, portletActions);
940    
941                    if (primKey == null) {
942                            return;
943                    }
944    
945                    // Individual
946    
947                    Resource resource = getResource(
948                            companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
949    
950                    // Permissions
951    
952                    boolean flushResourceBlockEnabled =
953                            PermissionThreadLocal.isFlushResourceBlockEnabled(
954                                    companyId, groupId, name);
955                    boolean flushResourcePermissionEnabled =
956                            PermissionThreadLocal.isFlushResourcePermissionEnabled(
957                                    name, primKey);
958    
959                    PermissionThreadLocal.setFlushResourceBlockEnabled(
960                            companyId, groupId, name, false);
961                    PermissionThreadLocal.setFlushResourcePermissionEnabled(
962                            name, primKey, false);
963    
964                    List<ResourcePermission> resourcePermissions =
965                            resourcePermissionPersistence.findByC_N_S_P(
966                                    companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
967    
968                    ResourcePermissionsThreadLocal.setResourcePermissions(
969                            resourcePermissions);
970    
971                    try {
972                            addResources(
973                                    companyId, groupId, userId, resource, portletActions,
974                                    permissionedModel);
975    
976                            // Group permissions
977    
978                            if ((groupId > 0) && addGroupPermissions) {
979                                    addGroupPermissions(
980                                            companyId, groupId, userId, name, resource, portletActions,
981                                            permissionedModel);
982                            }
983    
984                            // Guest permissions
985    
986                            if (addGuestPermissions) {
987    
988                                    // Don't add guest permissions when you've already added group
989                                    // permissions and the given group is the guest group.
990    
991                                    addGuestPermissions(
992                                            companyId, groupId, userId, name, resource, portletActions,
993                                            permissionedModel);
994                            }
995                    }
996                    finally {
997                            ResourcePermissionsThreadLocal.setResourcePermissions(null);
998    
999                            PermissionThreadLocal.setFlushResourceBlockEnabled(
1000                                    companyId, groupId, name, flushResourceBlockEnabled);
1001                            PermissionThreadLocal.setFlushResourcePermissionEnabled(
1002                                    name, primKey, flushResourcePermissionEnabled);
1003    
1004                            PermissionCacheUtil.clearResourceBlockCache(
1005                                    companyId, groupId, name);
1006                            PermissionCacheUtil.clearResourcePermissionCache(
1007                                    ResourceConstants.SCOPE_INDIVIDUAL, name, primKey);
1008    
1009                            SearchEngineUtil.updatePermissionFields(name, primKey);
1010                    }
1011            }
1012    
1013            protected void deleteResource(
1014                            long companyId, String name, int scope, String primKey,
1015                            PermissionedModel permissionedModel)
1016                    throws PortalException {
1017    
1018                    if (resourceBlockLocalService.isSupported(name)) {
1019                            if (permissionedModel == null) {
1020                                    throw new IllegalArgumentException(
1021                                            "Permissioned model is null");
1022                            }
1023    
1024                            resourceBlockLocalService.releasePermissionedModelResourceBlock(
1025                                    permissionedModel);
1026    
1027                            return;
1028                    }
1029    
1030                    resourcePermissionLocalService.deleteResourcePermissions(
1031                            companyId, name, scope, primKey);
1032            }
1033    
1034            protected void filterOwnerActions(String name, List<String> actionIds) {
1035                    List<String> defaultOwnerActions =
1036                            ResourceActionsUtil.getModelResourceOwnerDefaultActions(name);
1037    
1038                    if (defaultOwnerActions.isEmpty()) {
1039                            return;
1040                    }
1041    
1042                    Iterator<String> itr = actionIds.iterator();
1043    
1044                    while (itr.hasNext()) {
1045                            String actionId = itr.next();
1046    
1047                            if (!defaultOwnerActions.contains(actionId)) {
1048                                    itr.remove();
1049                            }
1050                    }
1051            }
1052    
1053            protected long getGroupId(AuditedModel auditedModel) {
1054                    long groupId = 0;
1055    
1056                    if (auditedModel instanceof GroupedModel) {
1057                            GroupedModel groupedModel = (GroupedModel)auditedModel;
1058    
1059                            groupId = BeanPropertiesUtil.getLongSilent(
1060                                    groupedModel, "resourceGroupId", groupedModel.getGroupId());
1061                    }
1062    
1063                    return groupId;
1064            }
1065    
1066            protected PermissionedModel getPermissionedModel(
1067                    AuditedModel auditedModel) {
1068    
1069                    PermissionedModel permissionedModel = null;
1070    
1071                    if (auditedModel instanceof PermissionedModel) {
1072                            permissionedModel = (PermissionedModel)auditedModel;
1073                    }
1074    
1075                    return permissionedModel;
1076            }
1077    
1078            protected Role getRole(long companyId, long groupId, String roleName)
1079                    throws PortalException {
1080    
1081                    if (roleName.equals(RoleConstants.PLACEHOLDER_DEFAULT_GROUP_ROLE)) {
1082                            if (groupId == 0) {
1083                                    throw new NoSuchRoleException(
1084                                            "Specify a group ID other than 0 for role name " +
1085                                                    RoleConstants.PLACEHOLDER_DEFAULT_GROUP_ROLE);
1086                            }
1087    
1088                            return roleLocalService.getDefaultGroupRole(groupId);
1089                    }
1090    
1091                    return roleLocalService.getRole(companyId, roleName);
1092            }
1093    
1094            protected void logHasUserPermissions(
1095                    long userId, long resourceId, String actionId, StopWatch stopWatch,
1096                    int block) {
1097    
1098                    if (!_log.isDebugEnabled()) {
1099                            return;
1100                    }
1101    
1102                    _log.debug(
1103                            "Checking user permissions block " + block + " for " + userId +
1104                                    " " + resourceId + " " + actionId + " takes " +
1105                                    stopWatch.getTime() + " ms");
1106            }
1107    
1108            protected void updateResourceBlocks(
1109                            long companyId, long groupId, Resource resource,
1110                            String[] groupPermissions, String[] guestPermissions,
1111                            PermissionedModel permissionedModel)
1112                    throws PortalException {
1113    
1114                    if (permissionedModel == null) {
1115                            throw new IllegalArgumentException("Permissioned model is null");
1116                    }
1117    
1118                    // Scope is assumed to always be individual
1119    
1120                    Role role = roleLocalService.getDefaultGroupRole(groupId);
1121    
1122                    resourceBlockLocalService.setIndividualScopePermissions(
1123                            companyId, groupId, resource.getName(), permissionedModel,
1124                            role.getRoleId(), Arrays.asList(groupPermissions));
1125    
1126                    role = roleLocalService.getRole(companyId, RoleConstants.GUEST);
1127    
1128                    resourceBlockLocalService.setIndividualScopePermissions(
1129                            companyId, groupId, resource.getName(), permissionedModel,
1130                            role.getRoleId(), Arrays.asList(guestPermissions));
1131            }
1132    
1133            protected void updateResourceBlocks(
1134                            long groupId, Resource resource, ModelPermissions modelPermissions,
1135                            PermissionedModel permissionedModel)
1136                    throws PortalException {
1137    
1138                    if (permissionedModel == null) {
1139                            throw new IllegalArgumentException("Permissioned model is null");
1140                    }
1141    
1142                    // Scope is assumed to always be individual
1143    
1144                    for (String roleName : modelPermissions.getRoleNames()) {
1145                            Role role = getRole(resource.getCompanyId(), groupId, roleName);
1146    
1147                            resourceBlockLocalService.setIndividualScopePermissions(
1148                                    role.getCompanyId(), groupId, resource.getName(),
1149                                    permissionedModel, role.getRoleId(),
1150                                    modelPermissions.getActionIdsList(roleName));
1151                    }
1152            }
1153    
1154            protected void updateResourcePermissions(
1155                            long companyId, long groupId, Resource resource,
1156                            String[] groupPermissions, String[] guestPermissions)
1157                    throws PortalException {
1158    
1159                    Role role = roleLocalService.getDefaultGroupRole(groupId);
1160    
1161                    resourcePermissionLocalService.setResourcePermissions(
1162                            resource.getCompanyId(), resource.getName(), resource.getScope(),
1163                            resource.getPrimKey(), role.getRoleId(), groupPermissions);
1164    
1165                    role = roleLocalService.getRole(companyId, RoleConstants.GUEST);
1166    
1167                    resourcePermissionLocalService.setResourcePermissions(
1168                            resource.getCompanyId(), resource.getName(), resource.getScope(),
1169                            resource.getPrimKey(), role.getRoleId(), guestPermissions);
1170            }
1171    
1172            protected void updateResourcePermissions(
1173                            long groupId, Resource resource, ModelPermissions modelPermissions)
1174                    throws PortalException {
1175    
1176                    for (String roleName : modelPermissions.getRoleNames()) {
1177                            Role role = getRole(resource.getCompanyId(), groupId, roleName);
1178    
1179                            List<String> actionIds = modelPermissions.getActionIdsList(
1180                                    roleName);
1181    
1182                            resourcePermissionLocalService.setResourcePermissions(
1183                                    resource.getCompanyId(), resource.getName(),
1184                                    resource.getScope(), resource.getPrimKey(), role.getRoleId(),
1185                                    actionIds.toArray(new String[actionIds.size()]));
1186                    }
1187            }
1188    
1189            protected void updateResourcePermissions(
1190                    long companyId, String name, int scope, String primKey,
1191                    String newPrimKey) {
1192    
1193                    List<ResourcePermission> resourcePermissions =
1194                            resourcePermissionLocalService.getResourcePermissions(
1195                                    companyId, name, scope, primKey);
1196    
1197                    for (ResourcePermission resourcePermission : resourcePermissions) {
1198                            resourcePermission.setPrimKey(newPrimKey);
1199                            resourcePermission.setPrimKeyId(GetterUtil.getLong(newPrimKey));
1200    
1201                            resourcePermissionPersistence.update(resourcePermission);
1202                    }
1203            }
1204    
1205            protected void updateResources(
1206                            long companyId, long groupId, String name, String primKey,
1207                            ModelPermissions modelPermissions,
1208                            PermissionedModel permissionedModel)
1209                    throws PortalException {
1210    
1211                    Resource resource = getResource(
1212                            companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
1213    
1214                    if (resourceBlockLocalService.isSupported(name)) {
1215                            updateResourceBlocks(
1216                                    groupId, resource, modelPermissions, permissionedModel);
1217                    }
1218                    else {
1219                            updateResourcePermissions(groupId, resource, modelPermissions);
1220                    }
1221            }
1222    
1223            protected void updateResources(
1224                            long companyId, long groupId, String name, String primKey,
1225                            String[] groupPermissions, String[] guestPermissions,
1226                            PermissionedModel permissionedModel)
1227                    throws PortalException {
1228    
1229                    Resource resource = getResource(
1230                            companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
1231    
1232                    if (groupPermissions == null) {
1233                            groupPermissions = new String[0];
1234                    }
1235    
1236                    if (guestPermissions == null) {
1237                            guestPermissions = new String[0];
1238                    }
1239    
1240                    if (resourceBlockLocalService.isSupported(name)) {
1241                            updateResourceBlocks(
1242                                    companyId, groupId, resource, groupPermissions,
1243                                    guestPermissions, permissionedModel);
1244                    }
1245                    else {
1246                            updateResourcePermissions(
1247                                    companyId, groupId, resource, groupPermissions,
1248                                    guestPermissions);
1249                    }
1250            }
1251    
1252            protected void validate(String name, boolean portletActions)
1253                    throws PortalException {
1254    
1255                    List<String> actions = null;
1256    
1257                    if (portletActions) {
1258                            actions = ResourceActionsUtil.getPortletResourceActions(name);
1259                    }
1260                    else {
1261                            actions = ResourceActionsUtil.getModelResourceActions(name);
1262                    }
1263    
1264                    if (actions.isEmpty()) {
1265                            throw new ResourceActionsException(
1266                                    "There are no actions associated with the resource " + name);
1267                    }
1268            }
1269    
1270            private static final Log _log = LogFactoryUtil.getLog(
1271                    ResourceLocalServiceImpl.class);
1272    
1273    }