package org.apache.maven.it;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import org.apache.maven.it.util.ResourceExtractor;

import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.util.security.Password;
import org.eclipse.jetty.servlet.ServletContextHandler;

import static org.eclipse.jetty.servlet.ServletContextHandler.SECURITY;
import static org.eclipse.jetty.servlet.ServletContextHandler.SESSIONS;
import static org.eclipse.jetty.util.security.Constraint.__BASIC_AUTH;

/**
 * This is a test set for <a href="https://issues.apache.org/jira/browse/MNG-553">MNG-553</a>.
 *
 * @author Benjamin Bentmann
 */
public class MavenITmng0553SettingsAuthzEncryptionTest
    extends AbstractMavenIntegrationTestCase
{

    private File testDir;

    private Server server;

    private int port;

    public MavenITmng0553SettingsAuthzEncryptionTest()
    {
        super( "[2.1.0,3.0-alpha-1),[3.0-alpha-3,)" );
    }

    @Override
    protected void setUp()
        throws Exception
    {
        testDir = ResourceExtractor.simpleExtractResources( getClass(), "/mng-0553" );

        Constraint constraint = new Constraint( __BASIC_AUTH, "user" );
        constraint.setAuthenticate( true );

        ConstraintMapping constraintMapping = new ConstraintMapping();
        constraintMapping.setConstraint( constraint );
        constraintMapping.setPathSpec( "/*" );

        HashLoginService userRealm = new HashLoginService( "TestRealm" );
        userRealm.putUser( "testuser", new Password( "testtest" ), new String[] { "user" } );

        server = new Server( 0 );
        ServletContextHandler ctx = new ServletContextHandler( server, "/", SESSIONS | SECURITY );
        ConstraintSecurityHandler securityHandler = (ConstraintSecurityHandler) ctx.getSecurityHandler();
        securityHandler.setLoginService( userRealm );
        securityHandler.setAuthMethod( __BASIC_AUTH );
        securityHandler.setConstraintMappings( new ConstraintMapping[] { constraintMapping } );

        ResourceHandler repoHandler = new ResourceHandler();
        repoHandler.setResourceBase( new File( testDir, "repo" ).getAbsolutePath() );

        HandlerList handlerList = new HandlerList();
        handlerList.addHandler( securityHandler );
        handlerList.addHandler( repoHandler );
        handlerList.addHandler( new DefaultHandler() );

        server.setHandler( handlerList );
        server.start();
        if ( server.isFailed() )
        {
            fail( "Couldn't bind the server socket to a free port!" );
        }
        port = ( (NetworkConnector) server.getConnectors()[0] ).getLocalPort();
        System.out.println( "Bound server socket to the port " + port );
    }

    @Override
    protected void tearDown()
        throws Exception
    {
        if ( server != null )
        {
            server.stop();
            server.join();
        }
    }

    /**
     * Test that the encrypted auth infos given in the settings.xml are decrypted.
     */
    public void testitBasic()
        throws Exception
    {
        testDir = new File( testDir, "test-1" );

        Properties filterProps = new Properties();
        filterProps.setProperty( "@port@", Integer.toString( port ) );

        Verifier verifier = newVerifier( testDir.getAbsolutePath() );
        verifier.setAutoclean( false );
        verifier.deleteArtifacts( "org.apache.maven.its.mng0553" );
        verifier.assertArtifactNotPresent( "org.apache.maven.its.mng0553", "a", "0.1-SNAPSHOT", "jar" );
        verifier.filterFile( "settings-template.xml", "settings.xml", "UTF-8", filterProps );
        setUserHome( verifier, new File( testDir, "userhome" ) );
        verifier.addCliOption( "--settings" );
        verifier.addCliOption( "settings.xml" );
        verifier.executeGoal( "validate" );
        verifier.verifyErrorFreeLog();
        verifier.resetStreams();

        verifier.assertArtifactPresent( "org.apache.maven.its.mng0553", "a", "0.1-SNAPSHOT", "jar" );
    }

    /**
     * Test that the encrypted auth infos given in the settings.xml are decrypted when the master password resides
     * in an external file.
     */
    public void testitRelocation()
        throws Exception
    {
        testDir = new File( testDir, "test-2" );

        Properties filterProps = new Properties();
        filterProps.setProperty( "@port@", Integer.toString( port ) );
        // NOTE: The upper-case scheme name is essential part of the test
        String secUrl = "FILE://" + new File( testDir, "relocated-settings-security.xml" ).toURI().getRawPath();
        filterProps.setProperty( "@relocation@", secUrl );

        Verifier verifier = newVerifier( testDir.getAbsolutePath() );
        verifier.setAutoclean( false );
        verifier.deleteArtifacts( "org.apache.maven.its.mng0553" );
        verifier.assertArtifactNotPresent( "org.apache.maven.its.mng0553", "a", "0.1-SNAPSHOT", "jar" );

        // NOTE: The tilde ~ in the file name is essential part of the test
        verifier.filterFile( "security-template.xml", "settings~security.xml", "UTF-8", filterProps );
        verifier.filterFile( "settings-template.xml", "settings.xml", "UTF-8", filterProps );

        verifier.getSystemProperties().setProperty( "settings.security",
            new File( testDir, "settings~security.xml" ).getAbsolutePath() );
        verifier.addCliOption( "--settings" );
        verifier.addCliOption( "settings.xml" );
        // NOTE: The selection of the Turkish language for the JVM locale is essential part of the test
        verifier.executeGoal( "validate", Collections.singletonMap( "MAVEN_OPTS", "-Duser.language=tr" ) );
        verifier.verifyErrorFreeLog();
        verifier.resetStreams();

        verifier.assertArtifactPresent( "org.apache.maven.its.mng0553", "a", "0.1-SNAPSHOT", "jar" );
    }

    /**
     * Test that the CLI supports generation of encrypted (master) passwords.
     */
    public void testitEncryption()
        throws Exception
    {
        requiresMavenVersion( "[2.1.0,3.0-alpha-1),[3.0-alpha-7,)" );

        testDir = new File( testDir, "test-3" );

        Verifier verifier = newVerifier( testDir.getAbsolutePath() );
        verifier.setAutoclean( false );
        setUserHome( verifier, new File( testDir, "userhome" ) );
        verifier.addCliOption( "--encrypt-master-password" );
        verifier.addCliOption( "test" );
        verifier.setLogFileName( "log-emp.txt" );
        verifier.executeGoal( "-e" );
        verifier.verifyErrorFreeLog();
        verifier.resetStreams();

        List<String> log = verifier.loadLines( verifier.getLogFileName(), null );
        assertNotNull( findPassword( log ) );

        verifier = newVerifier( testDir.getAbsolutePath() );
        verifier.setAutoclean( false );
        setUserHome( verifier, new File( testDir, "userhome" ) );
        verifier.addCliOption( "--encrypt-password" );
        verifier.addCliOption( "testpass" );
        verifier.setLogFileName( "log-ep.txt" );
        verifier.executeGoal( "-e" );
        verifier.verifyErrorFreeLog();
        verifier.resetStreams();

        log = verifier.loadLines( verifier.getLogFileName(), null );
        assertNotNull( findPassword( log ) );
    }

    private String findPassword( List<String> log )
    {
        for ( String line : log )
        {
            if ( line.matches( ".*\\{[A-Za-z0-9+/=]+\\}.*" ) )
            {
                return line;
            }
        }

        return null;
    }

    private void setUserHome( Verifier verifier, File home )
    {
        // NOTE: We set the user.home directory instead of say settings.security to reflect Maven's normal behavior
        String path = home.getAbsolutePath();
        if ( path.indexOf( ' ' ) < 0 )
        {
            verifier.setEnvironmentVariable( "MAVEN_OPTS", "-Duser.home=" + path );
        }
        else
        {
            verifier.setEnvironmentVariable( "MAVEN_OPTS", "\"-Duser.home=" + path + "\"" );
        }
    }
}
