SecurityHeaderService.java

  1. package fr.paris.lutece.portal.service.securityheader;

  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.Collections;
  5. import java.util.Comparator;
  6. import java.util.HashMap;
  7. import java.util.List;
  8. import java.util.Locale;
  9. import java.util.Map;
  10. import java.util.stream.Collectors;

  11. import org.apache.logging.log4j.LogManager;
  12. import org.apache.logging.log4j.Logger;

  13. import fr.paris.lutece.portal.business.securityheader.SecurityHeader;
  14. import fr.paris.lutece.portal.business.securityheader.SecurityHeaderHome;
  15. import fr.paris.lutece.portal.business.securityheader.SecurityHeaderPageCategory;
  16. import fr.paris.lutece.portal.business.securityheader.SecurityHeaderType;
  17. import fr.paris.lutece.util.ReferenceList;

  18. /**
  19.  * This class provides a service that offers methods to manage security headers.
  20.  */
  21. public class SecurityHeaderService
  22. {
  23.    
  24.     //This map contains the security headers loaded from the database. It prevents to make database calls when data are up to date.
  25.     //It must be refreshed each time that an action is performed. Currently, These actions are creating a new header, modifying an
  26.     //existing header, removing a header and enabling or disabling a header
  27.     private Map<String, SecurityHeader> _mapSecurityHeaders = new HashMap<String, SecurityHeader>( );
  28.    
  29.     Map<String, Map<String, List<SecurityHeader>>> _mapActiveSecurityHeadersForFilters = new HashMap<String, Map<String, List<SecurityHeader>>>( );
  30.    
  31.     //This boolean indicates if a refresh has been done on the security headers map. In other words, it tells if the map is up to date
  32.     //with data from database
  33.     private boolean _bMapRefreshDone = false;
  34.    
  35.     private Logger _logger = LogManager.getLogger( "lutece.securityHeader" );
  36.    
  37.     /**
  38.      * Returns all the security headers that match specified name, type and page category (if not null for the latter).
  39.      * If page category is null (REST api case), this criterion is ignored.
  40.      *
  41.      * @param strName
  42.      *           The name of the security header
  43.      * @param strType
  44.      *           The type of the security header
  45.      * @param pageCategory
  46.      *           The page category of the security header
  47.      * @return list od security headers matching the criteria
  48.      */
  49.     public List<SecurityHeader> find( String strName, String strType, String pageCategory )
  50.     {
  51.         ArrayList<SecurityHeader> securityHeadersResultList = new ArrayList<SecurityHeader>( );
  52.        
  53.         for( SecurityHeader securityHeader : findAll( ) )
  54.         {
  55.             if( securityHeader.getName( ).equals( strName ) && securityHeader.getType( ).equals( strType ) )
  56.             {
  57.                 if( pageCategory == null || securityHeader.getPageCategory( ).equals( pageCategory ) )
  58.                 {
  59.                     securityHeadersResultList.add( securityHeader );
  60.                 }              
  61.             }
  62.         }
  63.        
  64.         return securityHeadersResultList;
  65.     }
  66.    
  67.     /**
  68.      * Returns all security headers from the specified type and the specified category (if not null)
  69.      * that are active (attribute is_enable = true).
  70.      *
  71.      * @param strType
  72.      * @param strPageCategory
  73.      * @return collection on security headers
  74.      */
  75.     public Collection<SecurityHeader> findActive( String strType, String strPageCategory )
  76.     {
  77.         if( !_bMapRefreshDone )
  78.         {
  79.             refreshSecurityHeadersMap( SecurityHeaderHome.findAll() );
  80.         }
  81.         if( _mapActiveSecurityHeadersForFilters.get(strType) != null )
  82.         {
  83.             return _mapActiveSecurityHeadersForFilters.get( strType ).get( strPageCategory );
  84.         }
  85.         return null;
  86.     }
  87.    
  88.     /**
  89.      * Returns a collection of all security headers.
  90.      * Security headers are fetched from database (if data are stale) or from security headers map in memory (if the data in map are still up to date).
  91.      *
  92.      * @return collection of security headers
  93.      */
  94.     public Collection<SecurityHeader> findAll( )
  95.     {
  96.         Collection<SecurityHeader> securityHeadersList = null;
  97.        
  98.         if( _bMapRefreshDone )
  99.         {
  100.             securityHeadersList = _mapSecurityHeaders.values( );
  101.         }
  102.         else
  103.         {          
  104.             securityHeadersList = SecurityHeaderHome.findAll( );
  105.             refreshSecurityHeadersMap( securityHeadersList );  
  106.         }
  107.        
  108.         return securityHeadersList;
  109.     }
  110.    
  111.     /**
  112.      * Returns a list of all security headers used in manage security headers page. They are sorted by type, page category and name.
  113.      *
  114.      * @param locale
  115.      *           The locale
  116.      * @return list of all security headers
  117.      */
  118.     public List<SecurityHeader> findAllSorted( Locale locale )
  119.     {
  120.         List<SecurityHeader> securityHeadersList = findAll( ).stream().collect( Collectors.toList( ) );    
  121.         Collections.sort( securityHeadersList, Comparator.comparing( SecurityHeader::getType )
  122.                                                          .thenComparing( SecurityHeader::getPageCategory, Comparator.nullsLast( Comparator.naturalOrder( ) ) )
  123.                                                          .thenComparing( SecurityHeader::getName ) );
  124.        
  125.         return securityHeadersList;
  126.     }
  127.    
  128.     /**
  129.      * Returns the reference list of security headers types
  130.      *
  131.      * @return ReferenceList object with security headers types
  132.      */
  133.     public ReferenceList getTypeList( )
  134.     {
  135.         ReferenceList listTypes = new ReferenceList( );
  136.        
  137.         for (SecurityHeaderType type : SecurityHeaderType.values()) {
  138.             listTypes.addItem( type.getCode(), type.getCode() );
  139.         }
  140.        
  141.         return listTypes;
  142.     }
  143.    
  144.     /**
  145.      * Returns the reference list of security headers page categories
  146.      *
  147.      * @return ReferenceList object with security headers page categories
  148.      */
  149.     public ReferenceList getPageCategoryList( )
  150.     {
  151.         ReferenceList listPageCategory = new ReferenceList( );
  152.        
  153.         for (SecurityHeaderPageCategory pageCategory : SecurityHeaderPageCategory.values()) {
  154.             listPageCategory.addItem( pageCategory.getCode(), pageCategory.getCode() );
  155.         }
  156.        
  157.         return listPageCategory;
  158.     }
  159.    
  160.     /**
  161.      * Create the security header given in parameter. Like all the actions, this one invalidates the map containing the security headers.
  162.      *
  163.      * @param securityHeader
  164.      *                The security header to create
  165.      */
  166.     public void create( SecurityHeader securityHeader )
  167.     {
  168.         _logger.debug( "Security header to create : name : {}, value : {}, type : {}, page category : {}", securityHeader.getName( ), securityHeader.getValue( ), securityHeader.getType( ), securityHeader.getPageCategory( ) );
  169.         SecurityHeaderHome.create( securityHeader );
  170.         clearMapSecurityHeaders( );
  171.         _logger.debug( "Security header created" );
  172.     }

  173.     /**
  174.      * Update the security header given in parameter. Like all the actions, this one invalidates the map containing the security headers.
  175.      *
  176.      * @param securityHeader
  177.      *                The security header to update
  178.      */
  179.     public void update( SecurityHeader securityHeader )
  180.     {
  181.         _logger.debug( "Security header to update : id : {}, name : {}, value : {}, type : {}, page category : {}", securityHeader.getId( ), securityHeader.getName( ), securityHeader.getValue( ), securityHeader.getType( ), securityHeader.getPageCategory( ) );
  182.         SecurityHeaderHome.update( securityHeader );
  183.         clearMapSecurityHeaders( );
  184.         _logger.debug( "Security header updated" );
  185.     }
  186.    
  187.     /**
  188.      * Remove the security header given in parameter. Like all the actions, this one invalidates the map containing the security headers.
  189.      *
  190.      * @param securityHeader
  191.      *                The security header to remove
  192.      */
  193.     public void remove( int nSecurityHeaderId )
  194.     {
  195.         SecurityHeader securityHeader = _mapSecurityHeaders.get( String.valueOf( nSecurityHeaderId ) );
  196.         _logger.debug( "Security header to delete : id : {}, name : {}, value : {}, type : {}, page category : {}", securityHeader.getId( ), securityHeader.getName( ), securityHeader.getValue( ), securityHeader.getType( ), securityHeader.getPageCategory( ) );
  197.         SecurityHeaderHome.remove( nSecurityHeaderId );
  198.         clearMapSecurityHeaders( );
  199.         _logger.debug( "Security header deleted" );
  200.     }
  201.    
  202.     /**
  203.      * Enable the security header with the id given in parameter. Like all the actions, this one invalidates the map containing the security headers.
  204.      *
  205.      * @param nSecurityHeaderId
  206.      *                The id of the security header to enable
  207.      */
  208.     public void enable( int nSecurityHeaderId )
  209.     {
  210.         SecurityHeader securityHeader = _mapSecurityHeaders.get( String.valueOf( nSecurityHeaderId ) );
  211.         _logger.debug( "Security header to enable : id : {}, name : {}, value : {}, type : {}, page category : {}", securityHeader.getId( ), securityHeader.getName( ), securityHeader.getValue( ), securityHeader.getType( ), securityHeader.getPageCategory( ) );
  212.         SecurityHeaderHome.updateIsActive( nSecurityHeaderId, true );
  213.         clearMapSecurityHeaders( );
  214.         _logger.debug( "Security header enabled" );
  215.     }
  216.    
  217.     /**
  218.      * Disable the security header with the id given in parameter. Like all the actions, this one invalidates the map containing the security headers.
  219.      *
  220.      * @param nSecurityHeaderId
  221.      *                The id of the security header to disable
  222.      */
  223.     public void disable( int nSecurityHeaderId )
  224.     {
  225.         SecurityHeader securityHeader = _mapSecurityHeaders.get( String.valueOf( nSecurityHeaderId ) );
  226.         _logger.debug( "Security header to disable : id : {}, name : {}, value : {}, type : {}, page category : {}", securityHeader.getId( ), securityHeader.getName( ), securityHeader.getValue( ), securityHeader.getType( ), securityHeader.getPageCategory( ) );
  227.         SecurityHeaderHome.updateIsActive( nSecurityHeaderId, false );
  228.         clearMapSecurityHeaders( );
  229.         _logger.debug( "Security header disabled" );
  230.     }
  231.    
  232.     /**
  233.      * Clears the map containing the security headers
  234.      *
  235.      */
  236.     private void clearMapSecurityHeaders( )
  237.     {
  238.         _mapSecurityHeaders.clear( );
  239.         _mapActiveSecurityHeadersForFilters.clear( );
  240.         _bMapRefreshDone = false;
  241.         _logger.debug( "Security header maps cleared" );
  242.     }
  243.    
  244.     /**
  245.      * Refreshes the map of security headers with the list given in parameter. After a call to this method, data of the map are up to date with database data.
  246.      *
  247.      * @param securityHeadersList
  248.      *                 The security headers collection
  249.      */
  250.     private void refreshSecurityHeadersMap( Collection<SecurityHeader> securityHeadersList )
  251.     {
  252.         for( SecurityHeader securityHeader : securityHeadersList )
  253.         {
  254.             _mapSecurityHeaders.put( String.valueOf( securityHeader.getId( ) ), securityHeader );
  255.            
  256.             if( securityHeader.isActive() )
  257.             {
  258.                 _mapActiveSecurityHeadersForFilters.put( securityHeader.getType( ), addHeaderToTypeMap( securityHeader ) );
  259.             }                  
  260.         }
  261.         _bMapRefreshDone = true;
  262.         _logger.debug( "Security header map refreshed" );
  263.     }
  264.    
  265.     /**
  266.      * Adds a security header in the map of active security headers of the same type as the security header passed in parameter
  267.      *
  268.      * @param securityHeader Security header to add to the map
  269.      * @return map of active security headers of the same type as the security header passed in parameter updated with this security header
  270.      */
  271.     private Map<String, List<SecurityHeader>> addHeaderToTypeMap( SecurityHeader securityHeader )
  272.     {
  273.         //In _mapActiveSecurityHeadersForFilters, 2 keys are necessary to retrieve a list of security headers.
  274.         //For Page headers, those keys are respectively type and page category
  275.         //For Rest api headers, those keys are respectively type and null value.
  276.         //As page category is not irrelevant for rest api headers, they are grouped using the null key.
  277.         String firstKey = securityHeader.getType( );
  278.         Map<String, List<SecurityHeader>> mapHeadersForType = _mapActiveSecurityHeadersForFilters.get( firstKey );
  279.         List<SecurityHeader> headersListToUpdate = null;
  280.        
  281.         String secondKey = null;                    
  282.         if( securityHeader.getType( ).equals( SecurityHeaderType.PAGE.getCode( ) ) )
  283.         {
  284.             secondKey = securityHeader.getPageCategory( );
  285.         }
  286.        
  287.         if( mapHeadersForType == null )
  288.         {
  289.             mapHeadersForType = new HashMap<String, List<SecurityHeader>>( );
  290.             headersListToUpdate = new ArrayList<SecurityHeader>( );                
  291.         }
  292.         else
  293.         {                  
  294.             headersListToUpdate = mapHeadersForType.get( secondKey );
  295.             if( headersListToUpdate == null )
  296.             {
  297.                 headersListToUpdate = new ArrayList<SecurityHeader>( );                        
  298.             }
  299.         }
  300.         headersListToUpdate.add( securityHeader );
  301.         mapHeadersForType.put( secondKey, headersListToUpdate );
  302.        
  303.         return mapHeadersForType;
  304.     }
  305. }