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.documentation;
35  
36  import fr.paris.lutece.portal.business.right.FeatureGroup;
37  import fr.paris.lutece.portal.business.right.FeatureGroupHome;
38  import fr.paris.lutece.portal.business.right.Right;
39  import fr.paris.lutece.portal.business.user.AdminUser;
40  import fr.paris.lutece.portal.service.admin.AccessDeniedException;
41  import fr.paris.lutece.portal.service.admin.AdminUserService;
42  import fr.paris.lutece.portal.service.html.XmlTransformerService;
43  import fr.paris.lutece.portal.service.message.AdminMessage;
44  import fr.paris.lutece.portal.service.message.AdminMessageService;
45  import fr.paris.lutece.portal.service.template.AppTemplateService;
46  import fr.paris.lutece.portal.service.util.AppLogService;
47  import fr.paris.lutece.portal.service.util.AppPathService;
48  import fr.paris.lutece.portal.service.util.AppPropertiesService;
49  import fr.paris.lutece.util.html.HtmlTemplate;
50  import fr.paris.lutece.util.http.SecurityUtil;
51  
52  import java.io.File;
53  
54  import java.util.ArrayList;
55  import java.util.Collection;
56  import java.util.HashMap;
57  import java.util.List;
58  import java.util.Locale;
59  import java.util.Map;
60  
61  import javax.servlet.http.HttpServletRequest;
62  
63  import javax.xml.transform.stream.StreamSource;
64  
65  import org.apache.commons.collections.CollectionUtils;
66  import org.apache.commons.lang3.StringUtils;
67  
68  /**
69   *
70   * Classe for display the admin features documentation
71   *
72   */
73  public class AdminDocumentationJspBean
74  {
75      // xsl
76      private static final String XSL_PATH = "admin_documentation.xsl";
77  
78      // xsl paramaters
79      private static final String PARAMS_LOCAL = "locale";
80      private static final String PARAMS_DEFAULT_LOCAL = "default_locale";
81  
82      // parameters
83      private static final String PARAMETER_FEATURE_DOC = "doc";
84  
85      // jsp
86      private static final String JSP_CLOSE = "javascript:window.close()";
87  
88      // templates
89      private static final String TEMPLATE_ADMIN_SUMMARY_DOCUMENTATION = "admin/documentation/admin_summary_documentation.html";
90  
91      // bookmark
92      private static final String BOOKMARK_FEATURE_GROUP_LIST = "feature_group_list";
93      private static final String BOOKMARK_HELP_ICON = "help_icon";
94  
95      // images
96      private static final String IMAGE_HELP_PATH = "images/admin/skin/features/admin_help.png";
97  
98      // properties
99      private static final String PROPERTY_XSL_BASE_PATH = "lutece.documentation.xsl.path";
100     private static final String ADMIN_DOCUMENTATION_XSL_UNIQUE_PREFIX = "adminDocumentation-";
101 
102     // messages
103     private static final String MESSAGE_ERROR = "portal.features.documentation.message.error";
104 
105     // utils
106     private static final String LOCAL_DEFAULT = "en";
107     private static final String PROPERTY_XML_BASE_PATH = "lutece.xml.base.path";
108     private static final String PROPERTY_XML_USER_PATH = "lutece.xml.user.path";
109     private static final String FEATURES_GROUP_SYSTEM = "SYSTEM";
110 
111     /**
112      * Returns the view of features documentation
113      *
114      * @param request
115      *            The request
116      * @return The HTML documentation
117      * @throws AccessDeniedException
118      *             If the access is refused to the user
119      */
120     public String getDocumentation( HttpServletRequest request ) throws AccessDeniedException
121     {
122         String strFeature = request.getParameter( PARAMETER_FEATURE_DOC );
123 
124         if ( SecurityUtil.containsPathManipulationChars( request, strFeature ) )
125         {
126             return null;
127         }
128 
129         AdminUser user = AdminUserService.getAdminUser( request );
130         Locale locale = user.getLocale( );
131 
132         // get the xsl file
133         String strXslPath = AppPathService.getPath( PROPERTY_XSL_BASE_PATH, XSL_PATH );
134         File fileXsl = new File( strXslPath );
135         StreamSource sourceStyleSheet = new StreamSource( fileXsl );
136 
137         // get the xml documentation file
138         String xmlBasePath = AppPropertiesService.getProperty( PROPERTY_XML_BASE_PATH );
139         String userBasePath = AppPropertiesService.getProperty( PROPERTY_XML_USER_PATH );
140         String strXmlPath;
141         StreamSource sourceXml;
142 
143         if ( LOCAL_DEFAULT.equals( locale.toString( ) ) )
144         {
145             strXmlPath = AppPathService.getWebAppPath( ) + xmlBasePath + userBasePath + strFeature + ".xml";
146         }
147         else
148         {
149             strXmlPath = AppPathService.getWebAppPath( ) + xmlBasePath + locale.toString( ) + userBasePath + strFeature + ".xml";
150         }
151 
152         sourceXml = new StreamSource( new File( strXmlPath ) );
153 
154         String strHtmlDoc = null;
155 
156         Map<String, String> params = new HashMap<>( );
157         params.put( PARAMS_LOCAL, locale.toString( ) );
158         params.put( PARAMS_DEFAULT_LOCAL, LOCAL_DEFAULT );
159 
160         XmlTransformerServicervice.html#XmlTransformerService">XmlTransformerService xmlTransformerService = new XmlTransformerService( );
161         String strUniqueId = ADMIN_DOCUMENTATION_XSL_UNIQUE_PREFIX + strXmlPath;
162 
163         try
164         {
165             strHtmlDoc = xmlTransformerService.transformBySourceWithXslCache( sourceXml, sourceStyleSheet, strUniqueId, params, null );
166         }
167         catch( Exception e )
168         {
169             AppLogService.error( "Can't parse XML: {}", e.getMessage( ), e );
170 
171             return null;
172         }
173 
174         return strHtmlDoc;
175     }
176 
177     /**
178      * Returns an error message when an error occured
179      *
180      * @param request
181      *            The request
182      * @return The URL of message
183      */
184     public String doAdminMessage( HttpServletRequest request )
185     {
186         return AdminMessageService.getMessageUrl( request, MESSAGE_ERROR, JSP_CLOSE, AdminMessage.TYPE_ERROR );
187     }
188 
189     /**
190      * Returns the view of summary documentation
191      *
192      * @param request
193      *            The request
194      * @return The HTML documentation
195      */
196     public String getSummaryDocumentation( HttpServletRequest request )
197     {
198         AdminUser user = AdminUserService.getAdminUser( request );
199 
200         List<FeatureGroup> listFeatureGroups = getFeatureGroupsList( user );
201         Map<String, Object> model = new HashMap<>( );
202 
203         model.put( BOOKMARK_FEATURE_GROUP_LIST, listFeatureGroups );
204         model.put( BOOKMARK_HELP_ICON, IMAGE_HELP_PATH );
205 
206         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ADMIN_SUMMARY_DOCUMENTATION, user.getLocale( ), model );
207 
208         return template.getHtml( );
209     }
210 
211     /**
212      * Returns an array that contains all feature groups corresponding to the user
213      *
214      * @param user
215      *            The user
216      * @return A list of FeatureGroup objects
217      */
218     private List<FeatureGroup> getFeatureGroupsList( AdminUser user )
219     {
220         // structure that will be returned
221         ArrayList<FeatureGroup> aOutFeatureGroupList = new ArrayList<>( );
222 
223         // get the list of user's features
224         Map<String, Right> featuresMap = user.getRights( );
225         Collection<Right> features = featuresMap.values( );
226 
227         // for each group, load the features
228         for ( FeatureGroup featureGroup : FeatureGroupHome.getFeatureGroupsList( ) )
229         {
230             ArrayList<Right> aLeftFeatures = new ArrayList<>( );
231 
232             for ( Right right : features )
233             {
234                 right.setLocale( user.getLocale( ) );
235 
236                 String strFeatureGroup = right.getFeatureGroup( );
237                 String strUrlDocumentation = right.getDocumentationUrl( );
238 
239                 if ( featureGroup.getId( ).equalsIgnoreCase( strFeatureGroup ) && StringUtils.isNotEmpty( strUrlDocumentation ) )
240                 {
241                     featureGroup.addFeature( right );
242                 }
243                 else
244                     if ( StringUtils.isNotEmpty( strUrlDocumentation ) )
245                     {
246                         aLeftFeatures.add( right );
247                     }
248             }
249 
250             if ( !featureGroup.isEmpty( ) )
251             {
252                 featureGroup.setLocale( user.getLocale( ) );
253                 aOutFeatureGroupList.add( featureGroup );
254             }
255 
256             features = aLeftFeatures;
257         }
258 
259         FeatureGroup featureGroupSystem = FeatureGroupHome.findByPrimaryKey( FEATURES_GROUP_SYSTEM );
260 
261         if ( ( featureGroupSystem != null ) && !features.isEmpty( ) )
262         {
263             boolean bSystemFeaturesGroupExist = false;
264 
265             // Check if the features group system exist in list features group
266             for ( FeatureGroup featureGroup : aOutFeatureGroupList )
267             {
268                 // if exist
269                 if ( featureGroup.getId( ).equalsIgnoreCase( featureGroupSystem.getId( ) ) )
270                 {
271                     // add the features with no group to the list in features group SYSTEM
272                     for ( Right right : features )
273                     {
274                         featureGroup.addFeature( right );
275                     }
276 
277                     bSystemFeaturesGroupExist = true;
278 
279                     break;
280                 }
281             }
282 
283             // if not, add features group SYSTEM to the list with the feautres no group
284             if ( !bSystemFeaturesGroupExist )
285             {
286                 for ( Right right : features )
287                 {
288                     featureGroupSystem.addFeature( right );
289                 }
290 
291                 featureGroupSystem.setLocale( user.getLocale( ) );
292                 aOutFeatureGroupList.add( featureGroupSystem );
293             }
294         }
295         else
296             if ( CollectionUtils.isNotEmpty( aOutFeatureGroupList ) )
297             {
298                 FeatureGroup lastFeatureGroup = aOutFeatureGroupList.get( aOutFeatureGroupList.size( ) - 1 );
299 
300                 for ( Right right : features )
301                 {
302                     lastFeatureGroup.addFeature( right );
303                 }
304             }
305 
306         return aOutFeatureGroupList;
307     }
308 }