blob: 54b84ec5feed8f87ca977394dd4fff9b6d59a3cb [file] [log] [blame]
package org.apache.archiva.redback.rest.services.v2;
/*
* 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 com.fasterxml.jackson.databind.ser.Serializers;
import io.restassured.RestAssured;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants;
import org.apache.archiva.redback.rest.services.BaseSetup;
import org.apache.archiva.redback.role.RoleManager;
import org.apache.archiva.redback.role.RoleManagerException;
import org.apache.archiva.redback.users.User;
import org.apache.archiva.redback.users.UserManager;
import org.apache.archiva.redback.users.UserManagerException;
import org.apache.archiva.redback.users.UserNotFoundException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.jupiter.api.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.ContextLoaderListener;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import static io.restassured.RestAssured.*;
import static io.restassured.http.ContentType.JSON;
import static org.apache.archiva.redback.rest.services.BaseSetup.*;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* Native REST tests do not use the JAX-RS client and can be used with a remote
* REST API service. The tests
*
* @author Martin Stockhammer <martin_s@apache.org>
*/
@Tag( "rest-native" )
@Tag( "rest-v2" )
public abstract class AbstractNativeRestServices
{
public static final int STOPPED = 0;
public static final int STOPPING = 1;
public static final int STARTING = 2;
public static final int STARTED = 3;
public static final int ERROR = 4;
private final boolean startServer;
private final String serverPort;
private final String baseUri;
private RequestSpecification requestSpec;
protected Logger log = LoggerFactory.getLogger( getClass( ) );
private static AtomicReference<Server> server = new AtomicReference<>( );
private static AtomicReference<ServerConnector> serverConnector = new AtomicReference<>( );
private static AtomicInteger serverStarted = new AtomicInteger( STOPPED );
private UserManager userManager;
private RoleManager roleManager;
private final boolean remoteService;
private String adminToken;
private String adminRefreshToken;
public AbstractNativeRestServices( )
{
this.startServer = BaseSetup.startServer( );
this.serverPort = BaseSetup.getServerPort( );
this.baseUri = BaseSetup.getBaseUri( );
if ( startServer )
{
this.remoteService = false;
} else {
this.remoteService = true;
}
}
protected abstract String getServicePath( );
protected String getSpringConfigLocation( )
{
return "classpath*:spring-context.xml,classpath*:META-INF/spring-context.xml";
}
protected RequestSpecification getRequestSpec( )
{
return this.requestSpec;
}
protected String getContextRoot( )
{
return "/api";
}
private String getServiceBasePath( )
{
return "/v2/redback";
}
protected String getBasePath( )
{
return new StringBuilder( )
.append( getContextRoot( ) )
.append( getServiceBasePath( ) )
.append( getServicePath( ) ).toString( );
}
/**
* Returns the server that was started, or null if not initialized before.
*
* @return
*/
public Server getServer( )
{
return this.server.get( );
}
public int getServerPort( )
{
ServerConnector connector = serverConnector.get( );
if ( connector != null )
{
return connector.getLocalPort( );
}
else
{
return 0;
}
}
/**
* Returns true, if the server does exist and is running.
*
* @return true, if server does exist and is running.
*/
public boolean isServerRunning( )
{
return serverStarted.get( ) == STARTED && this.server.get( ) != null && this.server.get( ).isRunning( );
}
private UserManager getUserManager( )
{
if ( this.userManager == null )
{
UserManager userManager = ContextLoaderListener.getCurrentWebApplicationContext( )
.getBean( "userManager#default", UserManager.class );
assertNotNull( userManager );
this.userManager = userManager;
}
return this.userManager;
}
private RoleManager getRoleManager( )
{
if ( this.roleManager == null )
{
RoleManager roleManager = ContextLoaderListener.getCurrentWebApplicationContext( )
.getBean( "roleManager", RoleManager.class );
assertNotNull( roleManager );
this.roleManager = roleManager;
}
return this.roleManager;
}
protected String getAdminPwd( )
{
return BaseSetup.getAdminPwd( );
}
protected String getAdminUser( )
{
return RedbackRoleConstants.ADMINISTRATOR_ACCOUNT_NAME;
}
private void setupAdminUser( ) throws UserManagerException, RoleManagerException
{
UserManager um = getUserManager( );
User adminUser = null;
try
{
adminUser = um.findUser( getAdminUser( ) );
}
catch ( UserNotFoundException e )
{
// ignore
}
adminUser = um.createUser( getAdminUser( ), "Administrator", "admin@local.home" );
adminUser.setUsername( getAdminUser( ) );
adminUser.setPassword( getAdminPwd( ) );
adminUser.setFullName( "the admin user" );
adminUser.setEmail( "toto@toto.fr" );
adminUser.setPermanent( true );
adminUser.setValidated( true );
adminUser.setLocked( false );
adminUser.setPasswordChangeRequired( false );
if ( adminUser == null )
{
um.addUser( adminUser );
}
else
{
um.updateUser( adminUser, false );
}
getRoleManager( ).assignRole( "system-administrator", adminUser.getUsername( ) );
}
public void startServer( )
throws Exception
{
if ( serverStarted.compareAndSet( STOPPED, STARTING ) )
{
try
{
log.info( "Starting server" );
Server myServer = new Server( );
this.server.set( myServer );
this.serverConnector.set( new ServerConnector( myServer, new HttpConnectionFactory( ) ) );
myServer.addConnector( serverConnector.get( ) );
ServletHolder servletHolder = new ServletHolder( new CXFServlet( ) );
ServletContextHandler context = new ServletContextHandler( ServletContextHandler.SESSIONS );
context.setResourceBase( SystemUtils.JAVA_IO_TMPDIR );
context.setSessionHandler( new SessionHandler( ) );
context.addServlet( servletHolder, getContextRoot( ) + "/*" );
context.setInitParameter( "contextConfigLocation", getSpringConfigLocation( ) );
context.addEventListener( new ContextLoaderListener( ) );
getServer( ).setHandler( context );
getServer( ).start( );
if ( log.isDebugEnabled( ) )
{
log.debug( "Jetty dump: {}", getServer( ).dump( ) );
}
setupAdminUser( );
log.info( "Started server on port {}", getServerPort( ) );
serverStarted.set( STARTED );
}
finally
{
// In case, if the last statement was not reached
serverStarted.compareAndSet( STARTING, ERROR );
}
}
}
public void stopServer( )
throws Exception
{
if ( this.serverStarted.compareAndSet( STARTED, STOPPING ) )
{
try
{
final Server myServer = getServer( );
if ( myServer != null )
{
log.info( "Stopping server" );
myServer.stop( );
}
serverStarted.set( STOPPED );
}
finally
{
serverStarted.compareAndSet( STOPPING, ERROR );
}
}
else
{
log.error( "Serer is not in STARTED state!" );
}
}
protected void setupNative( ) throws Exception
{
if ( this.startServer )
{
startServer( );
}
if ( StringUtils.isNotEmpty( serverPort ) )
{
RestAssured.port = Integer.parseInt( serverPort );
}
else
{
RestAssured.port = getServerPort( );
}
if ( StringUtils.isNotEmpty( baseUri ) )
{
RestAssured.baseURI = baseUri;
}
else
{
RestAssured.baseURI = "http://localhost";
}
String basePath = getBasePath( );
this.requestSpec = getRequestSpecBuilder( ).build( );
RestAssured.basePath = basePath;
}
protected RequestSpecBuilder getRequestSpecBuilder( )
{
return new RequestSpecBuilder( ).setBaseUri( baseURI )
.setPort( port )
.setBasePath( getBasePath( ) )
.addHeader( "Origin", RestAssured.baseURI + ":" + RestAssured.port );
}
protected RequestSpecBuilder getAuthRequestSpecBuilder( )
{
return new RequestSpecBuilder( ).setBaseUri( baseURI )
.setPort( port )
.setBasePath( new StringBuilder( )
.append( getContextRoot( ) )
.append( getServiceBasePath( ) ).append("/auth").toString() )
.addHeader( "Origin", RestAssured.baseURI + ":" + RestAssured.port );
}
protected RequestSpecification getRequestSpec( String bearerToken )
{
return getRequestSpecBuilder( ).addHeader( "Authorization", "Bearer " + bearerToken ).build( );
}
protected void shutdownNative( ) throws Exception
{
if (startServer)
{
stopServer( );
}
}
protected org.apache.archiva.redback.rest.api.model.User addRemoteUser(String userid, String password, String fullName, String mail) {
return null;
}
protected void initAdminToken() {
Map<String, Object> jsonAsMap = new HashMap<>();
jsonAsMap.put( "grant_type", "authorization_code" );
jsonAsMap.put("user_id", getAdminUser());
jsonAsMap.put("password", getAdminPwd() );
Response result = given( ).spec( getAuthRequestSpecBuilder().build() )
.contentType( JSON )
.body( jsonAsMap )
.when( ).post( "/authenticate").then( ).statusCode( 200 )
.extract( ).response( );
this.adminToken = result.body( ).jsonPath( ).getString( "access_token" );
this.adminRefreshToken = result.body( ).jsonPath( ).getString( "refresh_token" );
}
protected String getAdminToken() {
if (this.adminToken == null) {
initAdminToken();
}
return this.adminToken;
}
protected String getAdminRefreshToken() {
if (this.adminRefreshToken == null) {
initAdminToken();
}
return this.adminRefreshToken;
}
public boolean isRemoteService() {
return this.remoteService;
}
}