/*
* Copyright (c) 2002-2015, Mairie de Paris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice
* and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* License 1.0
*/
package fr.paris.lutece.portal.service.portal;
import fr.paris.lutece.portal.business.page.Page;
import fr.paris.lutece.portal.service.init.LuteceInitException;
import fr.paris.lutece.portal.service.page.IPageService;
import fr.paris.lutece.portal.service.security.LuteceUser;
import fr.paris.lutece.portal.service.security.MokeLuteceAuthentication;
import fr.paris.lutece.portal.service.security.SecurityService;
import fr.paris.lutece.portal.service.spring.SpringContextService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
import fr.paris.lutece.test.LuteceTestCase;
import fr.paris.lutece.test.MokeHttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Properties;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
public class PortalMenuServiceTest extends LuteceTestCase
{
private static final String ROLE1 = "ROLE1";
private static final String ROLE2 = "ROLE2";
public void testGetMenuContent( )
{
HttpServletRequest request = new MokeHttpServletRequest( );
// determine a random page name
String randomPageName = "page" + new SecureRandom( ).nextLong( );
// get the menu
String menu = PortalMenuService.getInstance( ).getMenuContent( 0, PortalMenuService.MODE_NORMAL, PortalMenuService.MENU_MAIN, request );
assertFalse( "Portal menu should not contain not yet created page with name " + randomPageName, menu.contains( randomPageName ) );
// create the page
Page page = new Page( );
page.setParentPageId( PortalService.getRootPageId( ) );
page.setName( randomPageName );
IPageService pageService = (IPageService) SpringContextService.getBean( "pageService" );
pageService.createPage( page );
// get the menu
menu = PortalMenuService.getInstance( ).getMenuContent( 0, PortalMenuService.MODE_NORMAL, PortalMenuService.MENU_MAIN, request );
assertTrue( "Portal menu should contain page with name " + randomPageName, menu.contains( randomPageName ) );
// change the page name
randomPageName = randomPageName + "_mod";
page.setName( randomPageName );
pageService.updatePage( page );
// get the menu
menu = PortalMenuService.getInstance( ).getMenuContent( 0, PortalMenuService.MODE_NORMAL, PortalMenuService.MENU_MAIN, request );
assertTrue( "Portal menu should contain page with the modified name " + randomPageName, menu.contains( randomPageName ) );
// remove the page
pageService.removePage( page.getId( ) );
// get the menu
menu = PortalMenuService.getInstance( ).getMenuContent( 0, PortalMenuService.MODE_NORMAL, PortalMenuService.MENU_MAIN, request );
assertFalse( "Portal menu should not contain page with name " + randomPageName + " anymore", menu.contains( randomPageName ) );
}
public void testPageVisibility( ) throws IOException, LuteceInitException
{
// create pages
final Random rand = new SecureRandom( );
Page pageNoRole = createPage( "page." + rand.nextLong( ) );
Page pageRole1 = createPage( "page.role1." + rand.nextLong( ), ROLE1 );
Page pageRole2 = createPage( "page.role2." + rand.nextLong( ), ROLE2 );
boolean authStatus = enableAuthentication( );
boolean cacheStatus = enablePortalMenuServiceCache( );
try
{
// test twice to test the cache
for ( int i = 0; i < 2; i++ )
{
// test menu content with no user
HttpServletRequest request = new MokeHttpServletRequest( );
String menu = PortalMenuService.getInstance( ).getMenuContent( 0, PortalMenuService.MODE_NORMAL, PortalMenuService.MENU_MAIN, request );
assertTrue( "Portal menu should contain page not associated with a role named " + pageNoRole.getName( ) + " (call " + ( i + 1 ) + ")",
menu.contains( pageNoRole.getName( ) ) );
assertFalse( "Portal menu should not contain page associated with role " + ROLE1 + " named " + pageRole1.getName( ) + " (call " + ( i + 1 )
+ ")", menu.contains( pageRole1.getName( ) ) );
assertFalse( "Portal menu should not contain page associated with role " + ROLE2 + " named " + pageRole2.getName( ) + " (call " + ( i + 1 )
+ ")", menu.contains( pageRole2.getName( ) ) );
// test menu content with no role
@SuppressWarnings( "serial" )
LuteceUser user = new LuteceUser( "junit", SecurityService.getInstance( ).getAuthenticationService( ) )
{
@Override
public String getName( )
{
// user name is different on each call
return "user" + rand.nextLong( );
}
};
request.getSession( ).setAttribute( "lutece_user", user );
menu = PortalMenuService.getInstance( ).getMenuContent( 0, PortalMenuService.MODE_NORMAL, PortalMenuService.MENU_MAIN, request );
assertTrue( "Portal menu should contain page not associated with a role named " + pageNoRole.getName( ) + " (call " + ( i + 1 ) + ")",
menu.contains( pageNoRole.getName( ) ) );
assertFalse( "Portal menu should not contain page associated with role " + ROLE1 + " named " + pageRole1.getName( ) + " (call " + ( i + 1 )
+ ")", menu.contains( pageRole1.getName( ) ) );
assertFalse( "Portal menu should not contain page associated with role " + ROLE2 + " named " + pageRole2.getName( ) + " (call " + ( i + 1 )
+ ")", menu.contains( pageRole2.getName( ) ) );
// test menu content with ROLE1
user.setRoles( Arrays.asList( ROLE1 ) );
menu = PortalMenuService.getInstance( ).getMenuContent( 0, PortalMenuService.MODE_NORMAL, PortalMenuService.MENU_MAIN, request );
assertTrue( "Portal menu should contain page not associated with a role named " + pageNoRole.getName( ) + " (call " + ( i + 1 ) + ")",
menu.contains( pageNoRole.getName( ) ) );
assertTrue( "Portal menu should contain page associated with role " + ROLE1 + " named " + pageRole1.getName( ) + " (call " + ( i + 1 ) + ")",
menu.contains( pageRole1.getName( ) ) );
assertFalse( "Portal menu should not contain page associated with role " + ROLE2 + " named " + pageRole2.getName( ) + " (call " + ( i + 1 )
+ ")", menu.contains( pageRole2.getName( ) ) );
// test menu content with ROLE2
user.setRoles( Arrays.asList( ROLE2 ) );
menu = PortalMenuService.getInstance( ).getMenuContent( 0, PortalMenuService.MODE_NORMAL, PortalMenuService.MENU_MAIN, request );
assertTrue( "Portal menu should contain page not associated with a role named " + pageNoRole.getName( ) + " (call " + ( i + 1 ) + ")",
menu.contains( pageNoRole.getName( ) ) );
assertFalse( "Portal menu should not contain page associated with role " + ROLE1 + " named " + pageRole1.getName( ) + " (call " + ( i + 1 )
+ ")", menu.contains( pageRole1.getName( ) ) );
assertTrue( "Portal menu should contain page associated with role " + ROLE2 + " named " + pageRole2.getName( ) + " (call " + ( i + 1 ) + ")",
menu.contains( pageRole2.getName( ) ) );
// test menu content with ROLE1 and ROLE2
user.setRoles( Arrays.asList( ROLE1, ROLE2 ) );
menu = PortalMenuService.getInstance( ).getMenuContent( 0, PortalMenuService.MODE_NORMAL, PortalMenuService.MENU_MAIN, request );
assertTrue( "Portal menu should contain page not associated with a role named " + pageNoRole.getName( ) + " (call " + ( i + 1 ) + ")",
menu.contains( pageNoRole.getName( ) ) );
assertTrue( "Portal menu should contain page associated with role " + ROLE1 + " named " + pageRole1.getName( ) + " (call " + ( i + 1 ) + ")",
menu.contains( pageRole1.getName( ) ) );
assertTrue( "Portal menu should contain page associated with role " + ROLE2 + " named " + pageRole2.getName( ) + " (call " + ( i + 1 ) + ")",
menu.contains( pageRole2.getName( ) ) );
// test menu content with ROLE2 and ROLE1
user.setRoles( Arrays.asList( ROLE2, ROLE1 ) );
String menu2 = PortalMenuService.getInstance( ).getMenuContent( 0, PortalMenuService.MODE_NORMAL, PortalMenuService.MENU_MAIN, request );
assertTrue( "Role order should not matter to the cache (call " + ( i + 1 ) + ")", menu == menu2 );
}
}
finally
{
// cleanup
restoreAuthentication( authStatus );
restorePortalMenuServiceCache( cacheStatus );
IPageService pageService = (IPageService) SpringContextService.getBean( "pageService" );
pageService.removePage( pageNoRole.getId( ) );
pageService.removePage( pageRole1.getId( ) );
pageService.removePage( pageRole2.getId( ) );
}
}
private void restorePortalMenuServiceCache( boolean status )
{
PortalMenuService.getInstance( ).enableCache( status );
}
private boolean enablePortalMenuServiceCache( )
{
boolean status = PortalMenuService.getInstance( ).isCacheEnable( );
PortalMenuService.getInstance( ).enableCache( true );
return status;
}
private void restoreAuthentication( boolean status ) throws IOException, LuteceInitException
{
if ( !status )
{
File luteceProperties = new File( getResourcesDir( ), "WEB-INF/conf/lutece.properties" );
Properties props = new Properties( );
InputStream is = new FileInputStream( luteceProperties );
props.load( is );
is.close( );
props.remove( "mylutece.authentication.enable" );
props.remove( "mylutece.authentication.class" );
OutputStream os = new FileOutputStream( luteceProperties );
props.store( os, "saved for junit " + this.getClass( ).getCanonicalName( ) );
os.close( );
AppPropertiesService.reloadAll( );
SecurityService.init( );
}
}
private boolean enableAuthentication( ) throws IOException, LuteceInitException
{
boolean status = SecurityService.isAuthenticationEnable( );
if ( !status )
{
File luteceProperties = new File( getResourcesDir( ), "WEB-INF/conf/lutece.properties" );
Properties props = new Properties( );
InputStream is = new FileInputStream( luteceProperties );
props.load( is );
is.close( );
props.setProperty( "mylutece.authentication.enable", "true" );
props.setProperty( "mylutece.authentication.class", MokeLuteceAuthentication.class.getName( ) );
OutputStream os = new FileOutputStream( luteceProperties );
props.store( os, "saved for junit " + this.getClass( ).getCanonicalName( ) );
os.close( );
AppPropertiesService.reloadAll( );
SecurityService.init( );
}
return status;
}
private Page createPage( String pageName, String role )
{
Page page = new Page( );
page.setParentPageId( PortalService.getRootPageId( ) );
page.setName( pageName );
if ( role != null )
{
page.setRole( role );
}
IPageService pageService = (IPageService) SpringContextService.getBean( "pageService" );
pageService.createPage( page );
return page;
}
private Page createPage( String pageName )
{
return createPage( pageName, null );
}
}