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.plugins.unittree.service.unit;
35  
36  import java.util.ArrayList;
37  import java.util.List;
38  import java.util.Map;
39  
40  import javax.inject.Inject;
41  import javax.servlet.http.HttpServletRequest;
42  
43  import org.springframework.transaction.annotation.Transactional;
44  
45  import fr.paris.lutece.plugins.unittree.business.unit.Unit;
46  import fr.paris.lutece.plugins.unittree.business.unit.UnitHome;
47  import fr.paris.lutece.portal.business.user.AdminUser;
48  import fr.paris.lutece.portal.business.user.AdminUserHome;
49  import fr.paris.lutece.portal.business.workgroup.AdminWorkgroupHome;
50  import fr.paris.lutece.portal.service.util.AppPropertiesService;
51  import fr.paris.lutece.util.ReferenceItem;
52  import fr.paris.lutece.util.ReferenceList;
53  
54  /**
55   *
56   * UnitUserService
57   *
58   */
59  public class UnitUserService implements IUnitUserService
60  {
61      private static final String PROPERTY_MULTI_AFFECTATION_ENABLED = "unittree.users.enableMultiAffectation";
62      private static final boolean DEFAULT_MULTI_AFFECTATION_ENABLED = false;
63      @Inject
64      private IUnitService _unitService;
65  
66      // GET
67  
68      /**
69       * {@inheritDoc}
70       */
71      @Override
72      public AdminUser getUser( int nIdUser )
73      {
74          return AdminUserHome.findByPrimaryKey( nIdUser );
75      }
76  
77      /**
78       * {@inheritDoc}
79       */
80      @Override
81      public List<AdminUser> getUsers( int nIdUnit, Map<String, Unit> mapIdUserUnit, boolean isInDepthSearch )
82      {
83          List<AdminUser> listAdminUsers = new ArrayList<AdminUser>( );
84  
85          // First add the users from the current unit
86          listAdminUsers.addAll( getUsers( nIdUnit, mapIdUserUnit ) );
87  
88          if ( isInDepthSearch )
89          {
90              // Then add the users from the sub units
91              for ( Unit subUnit : _unitService.getSubUnits( nIdUnit, false ) )
92              {
93                  // Recursive function in order to get all users from all sub units of the unit
94                  listAdminUsers.addAll( getUsers( subUnit.getIdUnit( ), mapIdUserUnit, isInDepthSearch ) );
95              }
96          }
97  
98          return listAdminUsers;
99      }
100 
101     /**
102      * {@inheritDoc}
103      */
104     @Override
105     public List<AdminUser> getAvailableUsers( AdminUser currentUser, int nIdUnit, boolean bMultiAffectationEnabled )
106     {
107         List<AdminUser> listUsers = new ArrayList<AdminUser>( );
108         Unit unit = _unitService.getUnit( nIdUnit, false );
109 
110         for ( AdminUser user : AdminUserHome.findUserList( ) )
111         {
112             if ( isUserAvailable( currentUser, user, unit, bMultiAffectationEnabled ) )
113             {
114                 listUsers.add( user );
115             }
116         }
117 
118         return listUsers;
119     }
120 
121     /**
122      * {@inheritDoc}
123      */
124     @Override
125     public List<AdminUser> getAvailableUsers( AdminUser currentUser, int nIdUnit )
126     {
127         boolean bMultiAffectationEnabled = isMultiAffectationEnabled( );
128 
129         return getAvailableUsers( currentUser, nIdUnit, bMultiAffectationEnabled );
130     }
131 
132     // PROCESS
133 
134     /**
135      * {@inheritDoc}
136      */
137     @Override
138     public void doProcessAddUser( int nIdUser, AdminUser currentUser, HttpServletRequest request )
139     {
140         for ( IUnitUserAttributeService service : UnitUserAttributeManager.getListUnitUserAttributeService( ) )
141         {
142             service.doAddUser( nIdUser, currentUser, request );
143         }
144     }
145 
146     /**
147      * {@inheritDoc}
148      */
149     @Override
150     public void doProcessModifyUser( int nIdUser, AdminUser currentUser, HttpServletRequest request )
151     {
152         for ( IUnitUserAttributeService service : UnitUserAttributeManager.getListUnitUserAttributeService( ) )
153         {
154             service.doModifyUser( nIdUser, currentUser, request );
155         }
156     }
157 
158     /**
159      * {@inheritDoc}
160      */
161     @Override
162     public void doProcessRemoveUser( int nIdUser, AdminUser currentUser, HttpServletRequest request )
163     {
164         for ( IUnitUserAttributeService service : UnitUserAttributeManager.getListUnitUserAttributeService( ) )
165         {
166             service.doRemoveUser( nIdUser, currentUser, request );
167         }
168     }
169 
170     // CHECKS
171 
172     /**
173      * {@inheritDoc}
174      */
175     @Override
176     public boolean isUserInUnit( int nIdUser, int nIdUnit )
177     {
178         return UnitHome.isUserInUnit( nIdUser, nIdUnit );
179     }
180 
181     // CRUD
182 
183     /**
184      * {@inheritDoc}
185      */
186     @Override
187     @Transactional( "unittree.transactionManager" )
188     public boolean addUserToUnit( int nIdUnit, int nIdUser )
189     {
190         if ( !isUserInUnit( nIdUser, nIdUnit ) )
191         {
192             Unit unit = UnitHome.findByPrimaryKey( nIdUnit );
193             List<Unit> listUnits = _unitService.getUnitsByIdUser( nIdUser, false );
194             boolean bMultiAffectationEnabled = isMultiAffectationEnabled( );
195 
196             if ( !bMultiAffectationEnabled && ( listUnits.size( ) > 0 ) )
197             {
198                 return false;
199             }
200 
201             for ( Unit userUnit : listUnits )
202             {
203                 if ( _unitService.isParent( unit, userUnit ) )
204                 {
205                     removeUserFromUnit( nIdUser, userUnit.getIdUnit( ) );
206                 }
207             }
208 
209             UnitHome.addUserToUnit( nIdUnit, nIdUser );
210 
211             return true;
212         }
213 
214         return false;
215     }
216 
217     /**
218      * {@inheritDoc}
219      */
220     @Override
221     @Transactional( "unittree.transactionManager" )
222     public void removeUserFromUnit( int nIdUser, int nIdUnit )
223     {
224         UnitHome.removeUserFromUnit( nIdUser, nIdUnit );
225     }
226 
227     /**
228      * {@inheritDoc}
229      */
230     @Override
231     @Transactional( "unittree.transactionManager" )
232     public void removeUsersFromUnit( int nIdUnit )
233     {
234         UnitHome.removeUsersFromUnit( nIdUnit );
235     }
236 
237     /**
238      * {@inheritDoc}
239      */
240     @Override
241     public boolean isMultiAffectationEnabled( )
242     {
243         return AppPropertiesService.getPropertyBoolean( PROPERTY_MULTI_AFFECTATION_ENABLED, DEFAULT_MULTI_AFFECTATION_ENABLED );
244     }
245 
246     // PRIVATE METHODS
247 
248     /**
249      * Tell if 2 users have groups in common
250      * 
251      * @param user1
252      *            User1
253      * @param user2
254      *            User2
255      * @return true or false
256      */
257     private boolean haveCommonWorkgroups( AdminUser user1, AdminUser user2 )
258     {
259         ReferenceList workgroups = AdminWorkgroupHome.getUserWorkgroups( user1 );
260 
261         if ( workgroups.size( ) == 0 )
262         {
263             return true;
264         }
265 
266         for ( ReferenceItem item : workgroups )
267         {
268             if ( AdminWorkgroupHome.isUserInWorkgroup( user2, item.getCode( ) ) )
269             {
270                 return true;
271             }
272         }
273 
274         return false;
275     }
276 
277     /**
278      * Check if the user is available
279      * 
280      * @param currentUser
281      *            the current user
282      * @param userToCheck
283      *            the user to check
284      * @param unit
285      *            the unit to check if the user is available for
286      * @param bMultiAffectationEnabled
287      *            Indicates if this method should allow a user to be in several units, or if it should return false if he is already in a unit.
288      * @return true if the user is available, false otherwise
289      */
290     private boolean isUserAvailable( AdminUser currentUser, AdminUser userToCheck, Unit unit, boolean bMultiAffectationEnabled )
291     {
292         List<Unit> listUnits = _unitService.getUnitsByIdUser( userToCheck.getUserId( ), false );
293 
294         if ( !bMultiAffectationEnabled && ( listUnits.size( ) > 0 ) )
295         {
296             return false;
297         }
298 
299         for ( Unit userUnit : listUnits )
300         {
301             // If the user is in the unit or in one if its parents
302             if ( ( userUnit.getIdUnit( ) == unit.getIdUnit( ) ) || _unitService.isParent( userUnit, unit ) )
303             {
304                 return false;
305             }
306         }
307 
308         // Check if the current user is admin => visibility to all users
309         if ( currentUser.isAdmin( ) )
310         {
311             return true;
312         }
313 
314         // Check if the current user is parent to the user to check
315         if ( currentUser.isParent( userToCheck ) )
316         {
317             // Then check if they have the same workgroup, or the user to check does not have any workgroup
318             if ( haveCommonWorkgroups( currentUser, userToCheck ) || !AdminWorkgroupHome.checkUserHasWorkgroup( userToCheck.getUserId( ) ) )
319             {
320                 return true;
321             }
322         }
323 
324         return false;
325     }
326 
327     /**
328      * Get the list of {@link AdminUser} from a given id unit
329      * 
330      * @param nIdUnit
331      *            the id unit
332      * @param mapIdUserUnit
333      *            the map of <idUser, Unit>
334      * @return a list of {@link AdminUser}
335      */
336     private List<AdminUser> getUsers( int nIdUnit, Map<String, Unit> mapIdUserUnit )
337     {
338         Unit unit = _unitService.getUnit( nIdUnit, false );
339         List<AdminUser> listUsers = new ArrayList<AdminUser>( );
340         List<Integer> listIdUsers = UnitHome.findIdsUser( nIdUnit );
341 
342         if ( ( listIdUsers != null ) && !listIdUsers.isEmpty( ) )
343         {
344             for ( int nIdUser : listIdUsers )
345             {
346                 AdminUser user = AdminUserHome.findByPrimaryKey( nIdUser );
347 
348                 if ( user != null )
349                 {
350                     listUsers.add( user );
351                     mapIdUserUnit.put( Integer.toString( user.getUserId( ) ), unit );
352                 }
353             }
354         }
355 
356         return listUsers;
357     }
358 }