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.web.admin;
35  
36  import java.io.Serializable;
37  import java.util.ArrayList;
38  import java.util.Collections;
39  import java.util.HashMap;
40  import java.util.List;
41  import java.util.Locale;
42  import java.util.Map;
43  
44  import javax.servlet.http.HttpServletRequest;
45  
46  import org.apache.commons.collections.CollectionUtils;
47  import org.apache.commons.lang3.StringUtils;
48  import org.apache.logging.log4j.LogManager;
49  import org.apache.logging.log4j.Logger;
50  
51  import fr.paris.lutece.portal.business.right.FeatureGroup;
52  import fr.paris.lutece.portal.business.right.FeatureGroupHome;
53  import fr.paris.lutece.portal.business.right.Right;
54  import fr.paris.lutece.portal.business.user.AdminUser;
55  import fr.paris.lutece.portal.business.user.AdminUserHome;
56  import fr.paris.lutece.portal.business.user.authentication.LuteceDefaultAdminUser;
57  import fr.paris.lutece.portal.business.user.menu.AccessibilityModeAdminUserMenuItemProvider;
58  import fr.paris.lutece.portal.business.user.menu.LanguageAdminUserMenuItemProvider;
59  import fr.paris.lutece.portal.service.admin.AccessDeniedException;
60  import fr.paris.lutece.portal.service.admin.AdminUserService;
61  import fr.paris.lutece.portal.service.dashboard.DashboardService;
62  import fr.paris.lutece.portal.service.dashboard.IDashboardComponent;
63  import fr.paris.lutece.portal.service.datastore.DatastoreService;
64  import fr.paris.lutece.portal.service.init.AppInfo;
65  import fr.paris.lutece.portal.service.message.AdminMessage;
66  import fr.paris.lutece.portal.service.message.AdminMessageService;
67  import fr.paris.lutece.portal.service.plugin.Plugin;
68  import fr.paris.lutece.portal.service.plugin.PluginService;
69  import fr.paris.lutece.portal.service.portal.PortalService;
70  import fr.paris.lutece.portal.service.security.SecurityTokenService;
71  import fr.paris.lutece.portal.service.spring.SpringContextService;
72  import fr.paris.lutece.portal.service.template.AppTemplateService;
73  import fr.paris.lutece.portal.service.user.menu.AdminUserMenuService;
74  import fr.paris.lutece.portal.service.util.AppLogService;
75  import fr.paris.lutece.portal.service.util.AppPathService;
76  import fr.paris.lutece.portal.service.util.AppPropertiesService;
77  import fr.paris.lutece.portal.web.constants.Markers;
78  import fr.paris.lutece.portal.web.constants.Messages;
79  import fr.paris.lutece.portal.web.constants.Parameters;
80  import fr.paris.lutece.portal.web.l10n.LocaleService;
81  import fr.paris.lutece.util.html.HtmlTemplate;
82  import fr.paris.lutece.util.password.IPassword;
83  import fr.paris.lutece.util.password.IPasswordFactory;
84  
85  /**
86   * This class provides the user interface to manage admin features ( manage, create, modify, remove)
87   */
88  public class AdminMenuJspBean implements Serializable
89  {
90      // ///////////////////////////////////////////////////////////////////////////////
91      // Constants
92      private static final String ERROR_INVALID_TOKEN = "Invalid security token";
93      public static final String PROPERTY_LOGOUT_URL = "lutece.admin.logout.url";
94      public static final String PROPERTY_MENU_DEFAULT_POS = "top";
95      public static final String PROPERTY_MENU_DATASTORE_POS = "portal.site.site_property.menu.position";
96      private static final long serialVersionUID = -8939026727319948581L;
97  
98      // Markers
99      private static final String MARK_FEATURE_GROUP_LIST = "feature_group_list";
100     private static final String MARK_USER = "user";
101     private static final String MARK_ADMIN_URL = "admin_url";
102     private static final String MARK_PROD_BASE_URL = "prod_base_url";
103     private static final String MARK_ADMIN_LOGOUT_URL = "admin_logout_url";
104     private static final String MARK_SITE_NAME = "site_name";
105     private static final String MARK_MENU_POS = "menu_pos";
106     private static final String MARK_DASHBOARD_ZONE = "dashboard_zone_";
107     private static final String MARK_JAVASCRIPT_FILE = "javascript_file";
108     private static final String MARK_JAVASCRIPT_FILES = "javascript_files";
109     private static final String MARK_PLUGIN_NAME = "plugin_name";
110     private static final String MARK_PLUGINS_LIST = "plugins_list";
111     private static final String MARK_ADMIN_AVATAR = "adminAvatar";
112     private static final String MARK_MINIMUM_PASSWORD_SIZE = "minimumPasswordSize";
113     private static final String MARK_USER_MENU_ITEMS = "userMenuItems";
114     private static final String MARK_LIST_LOGGER_INFO = "listLoggersInfo";
115 
116     // Templates
117     private static final String TEMPLATE_ADMIN_HOME = "admin/user/admin_home.html";
118     private static final String TEMPLATE_ADMIN_MENU_HEADER = "admin/user/admin_header.html";
119     private static final String TEMPLATE_ADMIN_MENU_FOOTER = "admin/user/admin_footer.html";
120     private static final String TEMPLATE_MODIFY_PASSWORD_DEFAULT_MODULE = "admin/user/modify_password_default_module.html";
121     private static final String TEMPLATE_STYLESHEET_LINK = "admin/stylesheet_link.html";
122     private static final String TEMPLATE_JAVASCRIPT_FILE = "admin/javascript_file.html";
123 
124     // Parameter
125     private static final String PARAMETER_LANGUAGE = "language";
126 
127     // Properties
128     private static final String PROPERTY_DEFAULT_FEATURE_ICON = "lutece.admin.feature.default.icon";
129     private static final String PROPERTY_DASHBOARD_ZONES = "lutece.dashboard.zones.count";
130     private static final int PROPERTY_DASHBOARD_ZONES_DEFAULT = 4;
131     private static final String REFERER = "referer";
132 
133     // Jsp
134     private static final String PROPERTY_JSP_URL_ADMIN_LOGOUT = "lutece.admin.logout.url";
135     private static final String MESSAGE_CONTROL_PASSWORD_NO_CORRESPONDING = "portal.users.message.password.confirm.error";
136     private static final String PASSWORD_ERROR = "portal.users.message.password.wrong.current";
137     private static final String PASSWORD_CURRENT_ERROR = "portal.users.message.password.new.equals.current";
138     private static final String MESSAGE_PASSWORD_REDIRECT = "portal.users.message.password.ok.redirect";
139     private static final String LOGGER_ACCESS = "lutece.adminaccess";
140 
141     private static String _strStylesheets;
142     private static boolean _bResetAdminStylesheets;
143     private static String _strJavascripts;
144     private boolean _bAdminAvatar = PluginService.isPluginEnable( "adminavatar" );
145     private static Logger _loggerAccess = LogManager.getLogger( LOGGER_ACCESS );
146 
147     /**
148      * Returns the Administration header menu
149      *
150      * @param request
151      *            The HttpServletRequest
152      * @return The html code of the header
153      */
154     public String getAdminMenuHeader( HttpServletRequest request )
155     {
156         Map<String, Object> model = new HashMap<>( );
157         String strSiteName = PortalService.getSiteName( );
158         AdminUser user = AdminUserService.getAdminUser( request );
159         List<FeatureGroup> aFeaturesGroupList = getFeatureGroupsList( user );
160 
161         // Displays the menus according to the rights of the users
162         model.put( MARK_SITE_NAME, strSiteName );
163         model.put( MARK_MENU_POS, DatastoreService.getInstanceDataValue( PROPERTY_MENU_DATASTORE_POS, PROPERTY_MENU_DEFAULT_POS ) );
164         model.put( MARK_FEATURE_GROUP_LIST, aFeaturesGroupList );
165         model.put( MARK_ADMIN_URL, AppPathService.getBaseUrl( request ) + AppPathService.getAdminMenuUrl( ) );
166         model.put( MARK_PROD_BASE_URL, AppPathService.getProdUrl( request ) );
167         model.put( MARK_USER, user );
168         if ( user.isAdmin( ) )
169         {
170         	model.put( MARK_LIST_LOGGER_INFO, AppLogService.getLoggersInfo( ) );
171         }
172 
173         String strLogoutUrl = AppPropertiesService.getProperty( PROPERTY_LOGOUT_URL );
174         model.put( MARK_ADMIN_LOGOUT_URL, ( strLogoutUrl == null ) ? "" : strLogoutUrl );
175 
176         int nZoneMax = AppPropertiesService.getPropertyInt( PROPERTY_DASHBOARD_ZONES, PROPERTY_DASHBOARD_ZONES_DEFAULT );
177         setDashboardData( model, user, request, nZoneMax );
178 
179         model.put( MARK_ADMIN_AVATAR, _bAdminAvatar );
180         AdminUserMenuService registry = SpringContextService.getBean( AdminUserMenuService.BEAN_NAME );
181         model.put( MARK_USER_MENU_ITEMS, registry.getItems( request ) );
182 
183         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ADMIN_MENU_HEADER, user.getLocale( ), model );
184 
185         return template.getHtml( );
186     }
187 
188     /**
189      * Returns the Administration footer menu
190      *
191      * @param request
192      *            The HttpServletRequest
193      * @return The html code of the header
194      */
195     public String getAdminMenuFooter( HttpServletRequest request )
196     {
197         Map<String, Object> model = new HashMap<>( );
198         String strFooterVersion = AppInfo.getVersion( );
199         String strFooterSiteName = PortalService.getSiteName( );
200         AdminUser user = AdminUserService.getAdminUser( request );
201         Locale locale = ( user != null ) ? user.getLocale( ) : LocaleService.getDefault( );
202         model.put( Markers.VERSION, strFooterVersion );
203         model.put( MARK_SITE_NAME, strFooterSiteName );
204         model.put( MARK_JAVASCRIPT_FILES, getAdminJavascripts( ) );
205 
206         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ADMIN_MENU_FOOTER, locale, model );
207 
208         traceAdminAccess( request );
209 
210         return template.getHtml( );
211     }
212 
213     /**
214      * Returns the html code of the menu of the users
215      * 
216      * @param request
217      *            The Http request
218      * @return The html code of the users menu
219      */
220     public String getAdminMenuUser( HttpServletRequest request )
221     {
222         AdminUser user = AdminUserService.getAdminUser( request );
223 
224         Map<String, Object> model = new HashMap<>( );
225 
226         setDashboardData( model, user, request );
227 
228         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ADMIN_HOME, user.getLocale( ), model );
229 
230         return template.getHtml( );
231     }
232 
233     /**
234      * Add dashboard data to the template's model
235      * 
236      * @param model
237      *            The template's model
238      * @param user
239      *            The Admin User
240      * @param request
241      *            HttpServletRequest
242      */
243     private void setDashboardData( Map<String, Object> model, AdminUser user, HttpServletRequest request )
244     {
245         List<IDashboardComponent> listDashboards = DashboardService.getInstance( ).getDashboards( user, request );
246         int nZoneMax = AppPropertiesService.getPropertyInt( PROPERTY_DASHBOARD_ZONES, PROPERTY_DASHBOARD_ZONES_DEFAULT );
247 
248         if ( CollectionUtils.isNotEmpty( listDashboards ) )
249         {
250             int nColumnCount = DashboardService.getInstance( ).getColumnCount( );
251 
252             // Personnalized dashboards for the nColumnCount first zones
253             for ( int i = 1; i <= nColumnCount; i++ )
254             {
255                 model.put( MARK_DASHBOARD_ZONE + i, DashboardService.getInstance( ).getDashboardData( listDashboards, user, i, request ) );
256             }
257 
258             // Default dashboards for the nColumnCount to nZoneMax zones
259             for ( int i = nColumnCount + 1; i < nZoneMax; i++ )
260             {
261                 model.put( MARK_DASHBOARD_ZONE + i, DashboardService.getInstance( ).getDashboardData( user, i, request ) );
262             }
263         }
264         else
265         {
266             for ( int i = 1; i < nZoneMax; i++ )
267             {
268                 model.put( MARK_DASHBOARD_ZONE + i, DashboardService.getInstance( ).getDashboardData( user, i, request ) );
269             }
270         }
271     }
272 
273     /**
274      * Add a specific dashboard data to the template's model
275      * 
276      * @param model
277      *            The template's model
278      * @param user
279      *            The Admin User
280      * @param request
281      *            HttpServletRequest
282      * @param nDashboardZone
283      *            the dashboard zone
284      */
285     private void setDashboardData( Map<String, Object> model, AdminUser user, HttpServletRequest request, int nDashboardZone )
286     {
287         model.put( MARK_DASHBOARD_ZONE + nDashboardZone, DashboardService.getInstance( ).getDashboardData( user, nDashboardZone, request ) );
288     }
289 
290     /**
291      * Returns an array that contains all feature groups corresponding to the user
292      *
293      * @param user
294      *            The Admin user
295      * @return An array of FeatureGroup objects
296      */
297     private List<FeatureGroup> getFeatureGroupsList( AdminUser user )
298     {
299         // structure that will be returned
300         ArrayList<FeatureGroup> aOutFeatureGroupList = new ArrayList<>( );
301 
302         // get the list of user's features
303         Map<String, Right> featuresMap = user.getRights( );
304         List<Right> features = new ArrayList<>( featuresMap.values( ) );
305 
306         List<Right> rightsToDelete = new ArrayList<>( );
307 
308         // delete features which have a null URL : these features does not have to be displayed in the menu
309         for ( Right right : features )
310         {
311             if ( right.getUrl( ) == null )
312             {
313                 rightsToDelete.add( right );
314             }
315         }
316 
317         features.removeAll( rightsToDelete );
318 
319         Collections.sort( features );
320 
321         // for each group, load the features
322         for ( FeatureGroup featureGroup : FeatureGroupHome.getFeatureGroupsList( ) )
323         {
324             ArrayList<Right> aLeftFeatures = new ArrayList<>( );
325 
326             for ( Right right : features )
327             {
328                 right.setLocale( user.getLocale( ) );
329                 right.setIconUrl( getFeatureIcon( right ) );
330 
331                 String strFeatureGroup = right.getFeatureGroup( );
332 
333                 if ( featureGroup.getId( ).equalsIgnoreCase( strFeatureGroup ) )
334                 {
335                     featureGroup.addFeature( right );
336                 }
337                 else
338                 {
339                     aLeftFeatures.add( right );
340                 }
341             }
342 
343             if ( !featureGroup.isEmpty( ) )
344             {
345                 featureGroup.setLocale( user.getLocale( ) );
346                 aOutFeatureGroupList.add( featureGroup );
347             }
348 
349             features = aLeftFeatures;
350         }
351 
352         // add the features with no group to the last group
353         if ( CollectionUtils.isNotEmpty( aOutFeatureGroupList ) )
354         {
355             FeatureGroup lastFeatureGroup = aOutFeatureGroupList.get( aOutFeatureGroupList.size( ) - 1 );
356 
357             for ( Right right : features )
358             {
359                 lastFeatureGroup.addFeature( right );
360             }
361         }
362 
363         return aOutFeatureGroupList;
364     }
365 
366     /**
367      * Change the current language of the user
368      *
369      * @param request
370      *            The HTTP request
371      * @return The forward Url
372      * @throws AccessDeniedException
373      *             if the security token is invalid
374      */
375     public String doChangeLanguage( HttpServletRequest request ) throws AccessDeniedException
376     {
377         if ( !SecurityTokenService.getInstance( ).validate( request, LanguageAdminUserMenuItemProvider.TEMPLATE ) )
378         {
379             throw new AccessDeniedException( ERROR_INVALID_TOKEN );
380         }
381         String strLanguage = request.getParameter( PARAMETER_LANGUAGE );
382         AdminUser user = AdminUserService.getAdminUser( request );
383         Locale locale = new Locale( strLanguage );
384         user.setLocale( locale );
385         AppPathService.getBaseUrl( request );
386 
387         return AppPathService.getBaseUrl( request ) + AppPathService.getAdminMenuUrl( );
388     }
389 
390     /**
391      * Gets the feature icon
392      * 
393      * @param right
394      *            The right
395      * @return The icon
396      */
397     private String getFeatureIcon( Right right )
398     {
399         String strIconUrl = AppPropertiesService.getProperty( PROPERTY_DEFAULT_FEATURE_ICON );
400 
401         if ( ( right.getIconUrl( ) != null ) && ( !right.getIconUrl( ).equals( "" ) ) )
402         {
403             strIconUrl = right.getIconUrl( );
404         }
405         else
406         {
407             String strPluginName = right.getPluginName( );
408             Plugin plugin = PluginService.getPlugin( strPluginName );
409 
410             if ( plugin != null )
411             {
412                 strIconUrl = plugin.getIconUrl( );
413             }
414         }
415 
416         return strIconUrl;
417     }
418 
419     /**
420      * Display the modification form for user password. This is used only by the default module. For other modules, custom implementation should be provided.
421      * 
422      * @param request
423      *            the http request
424      * @return the form allowing the modification of the user's password
425      */
426     public String getModifyDefaultAdminUserPassword( HttpServletRequest request )
427     {
428         AdminUser user = AdminUserService.getAdminUser( request );
429         Locale locale = user.getLocale( );
430         Map<String, Object> model = new HashMap<>( );
431         model.put( MARK_MINIMUM_PASSWORD_SIZE, AdminUserService.getIntegerSecurityParameter( AdminUserService.DSKEY_PASSWORD_MINIMUM_LENGTH ) );
432         model.put( SecurityTokenService.MARK_TOKEN, SecurityTokenService.getInstance( ).getToken( request, TEMPLATE_MODIFY_PASSWORD_DEFAULT_MODULE ) );
433         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MODIFY_PASSWORD_DEFAULT_MODULE, locale, model );
434 
435         return template.getHtml( );
436     }
437 
438     /**
439      * Perform the user password modification. This is used only by the default module. For other modules, custom implementation should be provided.
440      * 
441      * @param request
442      *            the http request
443      * @return the form allowing the modification of the user's password
444      * @throws AccessDeniedException
445      *             if the security token is invalid
446      */
447     public String doModifyDefaultAdminUserPassword( HttpServletRequest request ) throws AccessDeniedException
448     {
449         AdminUser user = AdminUserService.getAdminUser( request );
450 
451         String strCurrentPassword = request.getParameter( Parameters.PASSWORD_CURRENT );
452         String strNewPassword = request.getParameter( Parameters.NEW_PASSWORD );
453         String strConfirmNewPassword = request.getParameter( Parameters.CONFIRM_NEW_PASSWORD );
454 
455         LuteceDefaultAdminUser userStored = AdminUserHome.findLuteceDefaultAdminUserByPrimaryKey( user.getUserId( ) );
456 
457         IPassword password = userStored.getPassword( );
458 
459         // Mandatory Fields
460         if ( StringUtils.isEmpty( strCurrentPassword ) || StringUtils.isEmpty( strNewPassword ) || StringUtils.isEmpty( strConfirmNewPassword ) )
461         {
462             return AdminMessageService.getMessageUrl( request, Messages.MANDATORY_FIELDS, AdminMessage.TYPE_STOP );
463         }
464 
465         // Test the difference between the two fields of new password
466         if ( !strNewPassword.equals( strConfirmNewPassword ) )
467         {
468             return AdminMessageService.getMessageUrl( request, MESSAGE_CONTROL_PASSWORD_NO_CORRESPONDING, AdminMessage.TYPE_STOP );
469         }
470 
471         String strUrl = AdminUserService.checkPassword( request, strNewPassword, user.getUserId( ) );
472 
473         if ( StringUtils.isNotEmpty( strUrl ) )
474         {
475             return strUrl;
476         }
477 
478         // Test of the value of the current password
479         if ( !password.check( strCurrentPassword ) )
480         {
481             return AdminMessageService.getMessageUrl( request, PASSWORD_ERROR, AdminMessage.TYPE_STOP );
482         }
483 
484         // Test of control of difference between the new password and the current one
485         if ( strCurrentPassword.equals( strNewPassword ) )
486         {
487             return AdminMessageService.getMessageUrl( request, PASSWORD_CURRENT_ERROR, AdminMessage.TYPE_STOP );
488         }
489         if ( !SecurityTokenService.getInstance( ).validate( request, TEMPLATE_MODIFY_PASSWORD_DEFAULT_MODULE ) )
490         {
491             throw new AccessDeniedException( ERROR_INVALID_TOKEN );
492         }
493 
494         // Successful tests
495         IPasswordFactory passwordFactory = SpringContextService.getBean( IPasswordFactory.BEAN_NAME );
496         userStored.setPassword( passwordFactory.getPasswordFromCleartext( strNewPassword ) );
497         userStored.setPasswordReset( Boolean.FALSE );
498         userStored.setPasswordMaxValidDate( AdminUserService.getPasswordMaxValidDate( ) );
499         AdminUserHome.update( userStored );
500         AdminUserHome.insertNewPasswordInHistory( userStored.getPassword( ), userStored.getUserId( ) );
501 
502         return AdminMessageService.getMessageUrl( request, MESSAGE_PASSWORD_REDIRECT, AppPropertiesService.getProperty( PROPERTY_JSP_URL_ADMIN_LOGOUT ),
503                 AdminMessage.TYPE_INFO );
504     }
505 
506     /**
507      * Change the mode accessibility
508      * 
509      * @param request
510      *            {@link HttpServletRequest}
511      * @return The forward Url
512      * @throws AccessDeniedException
513      *             if the security token is invalid
514      */
515     public String doModifyAccessibilityMode( HttpServletRequest request ) throws AccessDeniedException
516     {
517         if ( !SecurityTokenService.getInstance( ).validate( request, AccessibilityModeAdminUserMenuItemProvider.TEMPLATE ) )
518         {
519             throw new AccessDeniedException( ERROR_INVALID_TOKEN );
520         }
521         AdminUser user = AdminUserService.getAdminUser( request );
522 
523         if ( user != null )
524         {
525             boolean bIsAccessible = !user.getAccessibilityMode( );
526             user.setAccessibilityMode( bIsAccessible );
527             AdminUserHome.update( user );
528         }
529 
530         String strReferer = request.getHeader( REFERER );
531 
532         if ( StringUtils.isNotBlank( strReferer ) )
533         {
534             return strReferer;
535         }
536 
537         return AppPathService.getBaseUrl( request ) + AppPathService.getAdminMenuUrl( );
538     }
539 
540     /**
541      * Return the stylesheets block to include in the footer
542      * 
543      * @return the stylesheets files block to include in the footer
544      * @since 5.1
545      */
546     public String getAdminStyleSheets( )
547     {
548         loadStylesheets( );
549         return _strStylesheets;
550     }
551 
552     private static synchronized void loadStylesheets( )
553     {
554         if ( _strStylesheets == null || _bResetAdminStylesheets )
555         {
556             List<Plugin> listPlugins = new ArrayList<>( );
557             listPlugins.add( PluginService.getCore( ) );
558             listPlugins.addAll( PluginService.getPluginList( ) );
559 
560             Map<String, Object> model = new HashMap<>( );
561             model.put( MARK_PLUGINS_LIST, listPlugins );
562 
563             _strStylesheets = AppTemplateService.getTemplate( TEMPLATE_STYLESHEET_LINK, LocaleService.getDefault( ), model ).getHtml( );
564             _bResetAdminStylesheets = false;
565         }
566     }
567 
568     public static void resetAdminStylesheets( )
569     {
570         _bResetAdminStylesheets = true;
571     }
572 
573     /**
574      * Return the javascript files block to include in the footer
575      * 
576      * @return the javascript files block to include in the footer
577      * @since 5.1
578      */
579     private static synchronized String getAdminJavascripts( )
580     {
581         if ( _strJavascripts == null )
582         {
583             StringBuilder sbJavascripts = new StringBuilder( );
584             List<Plugin> listPlugins = new ArrayList<>( );
585             listPlugins.add( PluginService.getCore( ) );
586             listPlugins.addAll( PluginService.getPluginList( ) );
587 
588             for ( Plugin plugin : listPlugins )
589             {
590                 if ( plugin.getAdminJavascriptFiles( ) != null )
591                 {
592                     for ( String strJavascript : plugin.getAdminJavascriptFiles( ) )
593                     {
594                         Map<String, Object> model = new HashMap<>( );
595                         model.put( MARK_JAVASCRIPT_FILE, strJavascript );
596                         model.put( MARK_PLUGIN_NAME, plugin.getName( ) );
597                         sbJavascripts.append( AppTemplateService.getTemplate( TEMPLATE_JAVASCRIPT_FILE, LocaleService.getDefault( ), model ).getHtml( ) );
598                     }
599                 }
600             }
601 
602             _strJavascripts = sbJavascripts.toString( );
603         }
604 
605         return _strJavascripts;
606     }
607 
608     /**
609      * Trace in a log file URL accessed by the current admin user
610      * 
611      * @param request
612      *            The HTTP request
613      */
614     private void traceAdminAccess( HttpServletRequest request )
615     {
616         AdminUser user = AdminUserService.getAdminUser( request );
617         if ( user != null )
618         {
619             StringBuilder sbAccessLog = new StringBuilder( );
620             sbAccessLog.append( "USER id:" ).append( user.getUserId( ) ).append( ", name: " ).append( user.getFirstName( ) ).append( " " )
621                     .append( user.getLastName( ) ).append( ", ip: " ).append( request.getRemoteAddr( ) ).append( ", url: " ).append( request.getScheme( ) )
622                     .append( "://" ).append( request.getServerName( ) ).append( ':' ).append( request.getServerPort( ) ).append( request.getRequestURI( ) );
623             String strQuery = request.getQueryString( );
624             if ( strQuery != null )
625             {
626                 sbAccessLog.append( "?" ).append( strQuery );
627             }
628             _loggerAccess.info( sbAccessLog.toString( ) );
629 
630         }
631     }
632 }