View Javadoc
1   /*
2    * Copyright (c) 2002-2022, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.portal.service.rbac;
35  
36  import fr.paris.lutece.api.user.User;
37  import fr.paris.lutece.api.user.UserRole;
38  import fr.paris.lutece.portal.business.rbac.RBAC;
39  import fr.paris.lutece.portal.business.rbac.RBACHome;
40  import fr.paris.lutece.portal.business.user.AdminUser;
41  import fr.paris.lutece.util.ReferenceItem;
42  import fr.paris.lutece.util.ReferenceList;
43  
44  import java.util.ArrayList;
45  import java.util.Collection;
46  import java.util.Collections;
47  import java.util.HashMap;
48  import java.util.Map;
49  import java.util.Set;
50  import java.util.stream.Collectors;
51  
52  /**
53   * This class provides the main methods to control the access to a resource depending on the user's roles
54   */
55  public final class RBACService
56  {
57  
58      /**
59       * ReferenceItem as an RBACResource
60       */
61      private static final class RBACReferenceItem implements RBACResource
62      {
63          private final String _strResourceType;
64          private final ReferenceItem _item;
65  
66          /**
67           * Constructor
68           * 
69           * @param strResourceType
70           *            the resource type
71           * @param item
72           *            the reference item
73           */
74          public RBACReferenceItem( String strResourceType, ReferenceItem item )
75          {
76              _strResourceType = strResourceType;
77              _item = item;
78          }
79  
80          @Override
81          public String getResourceTypeCode( )
82          {
83              return _strResourceType;
84          }
85  
86          @Override
87          public String getResourceId( )
88          {
89              return _item.getCode( );
90          }
91  
92          /**
93           * The reference item
94           * 
95           * @return the reference item
96           */
97          public ReferenceItem getItem( )
98          {
99              return _item;
100         }
101 
102     }
103 
104     /**
105      * Constructor
106      */
107     private RBACService( )
108     {
109     }
110 
111     /**
112      * Check that a given user is allowed to access a resource for a given permission
113      * 
114      * @param strResourceTypeCode
115      *            the key of the resource type being considered
116      * @param strResourceId
117      *            the id of the resource being considered
118      * @param strPermission
119      *            the permission needed
120      * @param user
121      *            the user trying to access the ressource
122      * @return true if the user can access the given resource with the given permission, false otherwise
123      */
124     public static boolean isAuthorized( String strResourceTypeCode, String strResourceId, String strPermission, User user )
125     {
126         // Check user roles
127         Collection<String> colRoles = RBACHome.findRoleKeys( strResourceTypeCode, strResourceId, strPermission );
128 
129         for ( String strRole : colRoles )
130         {
131             if ( isUserInRole( user, strRole ) )
132             {
133                 return true;
134             }
135         }
136 
137         return false;
138     }
139 
140     /**
141      * Check that a given user is allowed to access a resource for a given permission
142      * 
143      * @param strResourceTypeCode
144      *            the key of the resource type being considered
145      * @param strResourceId
146      *            the id of the resource being considered
147      * @param strPermission
148      *            the permission needed
149      * @param user
150      *            the user trying to access the ressource
151      * @return true if the user can access the given resource with the given permission, false otherwise
152      * @deprecated use isAuthorized( String, String, String, User )
153      */
154     @Deprecated
155     public static boolean isAuthorized( String strResourceTypeCode, String strResourceId, String strPermission, AdminUser user )
156     {
157         return isAuthorized( strResourceTypeCode, strResourceId, strPermission, (User) user );
158     }
159 
160     /**
161      * Check that a given user is allowed to access a resource for a given permission
162      * 
163      * @param resource
164      *            the resource object being considered
165      * @param strPermission
166      *            the permission needed
167      * @param user
168      *            the user trying to access the ressource
169      * @return true if the user can access the given resource with the given permission, false otherwise
170      */
171     public static boolean isAuthorized( RBACResource resource, String strPermission, User user )
172     {
173         boolean bAuthorized = false;
174 
175         if ( resource != null )
176         {
177             bAuthorized = isAuthorized( resource.getResourceTypeCode( ), resource.getResourceId( ), strPermission, user );
178         }
179 
180         return bAuthorized;
181     }
182 
183     /**
184      * Check that a given user is allowed to access a resource for a given permission
185      * 
186      * @param resource
187      *            the resource object being considered
188      * @param strPermission
189      *            the permission needed
190      * @param user
191      *            the user trying to access the ressource
192      * @return true if the user can access the given resource with the given permission, false otherwise
193      * @deprecated use isAuthorized( RBACResource, String, User )
194      */
195     @Deprecated
196     public static boolean isAuthorized( RBACResource resource, String strPermission, AdminUser user )
197     {
198         return isAuthorized( resource, strPermission, (User) user );
199     }
200 
201     /**
202      * Check that a given user is in the given role
203      * 
204      * @param user
205      *            The user
206      * @param strRole
207      *            The role
208      * @return true if the user has the given role, false otherwise
209      */
210     public static boolean isUserInRole( User user, String strRole )
211     {
212         Map<String, UserRole> userRoles = user.getUserRoles( );
213 
214         return userRoles.containsKey( strRole );
215     }
216 
217     /**
218      * Check that a given user is in the given role
219      * 
220      * @param user
221      *            The user
222      * @param strRole
223      *            The role
224      * @return true if the user has the given role, false otherwise
225      * @deprecated use isUserInRole( User, String )
226      */
227     @Deprecated
228     public static boolean isUserInRole( AdminUser user, String strRole )
229     {
230         return isUserInRole( (User) user, strRole );
231     }
232 
233     /**
234      * Filter a collection of resources for a given user
235      * 
236      * @param <E>
237      *            The RBAC resource
238      * @param collection
239      *            The collection to filter
240      * @param strPermission
241      *            Permission to check
242      * @param user
243      *            The user
244      * @return A filtered collection of resources
245      */
246     public static <E extends RBACResource> Collection<E> getAuthorizedCollection( Collection<E> collection, String strPermission, User user )
247     {
248         if ( user == null )
249         {
250             return Collections.emptyList( );
251         }
252         Map<String, Collection<RBAC>> rbacsByResourceType = new HashMap<>( );
253         RBACHome.findByPermissionAndRoles( strPermission, user.getUserRoles( ).keySet( ) ).stream( ).forEach( rbac -> {
254             rbacsByResourceType.computeIfAbsent( rbac.getResourceTypeKey( ), t -> new ArrayList<>( ) ).add( rbac );
255         } );
256         return collection.stream( )
257                 .filter( resource -> rbacsByResourceType
258                         .getOrDefault( resource.getResourceTypeCode( ), Collections.emptyList( ) ).stream( )
259                         .anyMatch( rbac -> RBAC.WILDCARD_RESOURCES_ID.equals( rbac.getResourceId( ) )
260                                 || resource.getResourceId( ).equals( rbac.getResourceId( ) ) ) )
261                 .collect( Collectors.toList( ) );
262     }
263 
264     /**
265      * Filter a collection of resources for a given user
266      * 
267      * @param <E>
268      *            The RBAC resource
269      * @param collection
270      *            The collection to filter
271      * @param strPermission
272      *            Permission to check
273      * @param user
274      *            The user
275      * @return A filtered collection of resources
276      * @deprecated use getAuthorizedCollection( Collection, String, User )
277      */
278     @Deprecated
279     public static <E extends RBACResource> Collection<E> getAuthorizedCollection( Collection<E> collection, String strPermission, AdminUser user )
280     {
281         return getAuthorizedCollection( collection, strPermission, (User) user );
282     }
283 
284     /**
285      * Filter a Reference List for a given user
286      * 
287      * @param listResources
288      *            The list to filter
289      * @param strResourceType
290      *            The resource type
291      * @param strPermission
292      *            The permission to check
293      * @param user
294      *            The user
295      * @return The filtered collection
296      */
297     public static ReferenceLists/lutece/util/ReferenceList.html#ReferenceList">ReferenceList getAuthorizedReferenceList( ReferenceList listResources, String strResourceType, String strPermission, User user )
298     {
299         return getAuthorizedCollection( listResources.stream( )
300                 .map( item -> new RBACReferenceItem( strResourceType, item ) ).collect( Collectors.toList( ) ),
301                 strPermission, user ).stream( ).map( RBACReferenceItem::getItem )
302                         .collect( Collectors.toCollection( ReferenceList::new ) );
303     }
304 
305     /**
306      * Filter a Reference List for a given user
307      * 
308      * @param listResources
309      *            The list to filter
310      * @param strResourceType
311      *            The resource type
312      * @param strPermission
313      *            The permission to check
314      * @param user
315      *            The user
316      * @return The filtered collection
317      * @deprecated use getAuthorizedReferenceList( ReferenceList, String, String, User )
318      */
319     @Deprecated
320     public static ReferenceLists/lutece/util/ReferenceList.html#ReferenceList">ReferenceList getAuthorizedReferenceList( ReferenceList listResources, String strResourceType, String strPermission, AdminUser user )
321     {
322         return getAuthorizedReferenceList( listResources, strResourceType, strPermission, (User) user );
323     }
324 
325     /**
326      * Filter a collection of RBACAction for a given user
327      * 
328      * @param <E>
329      *            The RBAC resource
330      * @param collection
331      *            The collection to filter
332      * @param resource
333      *            The resource
334      * @param user
335      *            The user
336      * @return The filtered collection
337      */
338     public static <E extends RBACAction> Collection<E> getAuthorizedActionsCollection( Collection<E> collection, RBACResource resource, User user )
339     {
340         if ( collection.isEmpty( ) )
341         {
342             return collection;
343         }
344         Set<String> permissions = RBACHome
345                 .findByPermissionsAndRoles(
346                         collection.stream( ).map( RBACAction::getPermission ).collect( Collectors.toSet( ) ),
347                         user.getUserRoles( ).keySet( ) )
348                 .stream( ).filter( rbac -> resource.getResourceTypeCode( ).equals( rbac.getResourceTypeKey( ) ) )
349                 .filter( rbac -> RBAC.WILDCARD_RESOURCES_ID.equals( rbac.getResourceId( ) )
350                         || resource.getResourceId( ).equals( rbac.getResourceId( ) ) )
351                 .map( RBAC::getPermissionKey ).collect( Collectors.toSet( ) );
352         return collection.stream( ).filter( action -> permissions.contains( action.getPermission( ) )
353                 || permissions.contains( RBAC.WILDCARD_PERMISSIONS_KEY ) ).collect( Collectors.toList( ) );
354     }
355 
356     /**
357      * Filter a collection of RBACAction for a given user
358      * 
359      * @param <E>
360      *            The RBAC resource
361      * @param collection
362      *            The collection to filter
363      * @param resource
364      *            The resource
365      * @param user
366      *            The user
367      * @return The filtered collection
368      * @deprecated use getAuthorizedActionsCollection( Collection, RBACResource, User )
369      */
370     @Deprecated
371     public static <E extends RBACAction> Collection<E> getAuthorizedActionsCollection( Collection<E> collection, RBACResource resource, AdminUser user )
372     {
373         return getAuthorizedActionsCollection( collection, resource, (User) user );
374     }
375 
376 }