Improving V2 REST services
This commit is contained in:
parent
8e6023173d
commit
8242f07b08
|
@ -21,7 +21,31 @@ package org.apache.archiva.redback.rest.api;
|
||||||
/**
|
/**
|
||||||
* @author Martin Stockhammer <martin_s@apache.org>
|
* @author Martin Stockhammer <martin_s@apache.org>
|
||||||
*/
|
*/
|
||||||
public class Constants
|
public interface Constants
|
||||||
{
|
{
|
||||||
public static final String DEFAULT_PAGE_LIMIT = "1000";
|
String DEFAULT_PAGE_LIMIT = "1000";
|
||||||
|
|
||||||
|
String ERR_UNKNOWN = "redback:unknown_error";
|
||||||
|
String ERR_USER_EXISTS = "redback:user.exists";
|
||||||
|
String ERR_USER_ID_EMPTY = "redback:user.id.empty";
|
||||||
|
String ERR_USER_FULL_NAME_EMPTY = "redback:user.fullname.empty";
|
||||||
|
String ERR_USER_EMAIL_EMPTY = "redback:user.email.empty";
|
||||||
|
String ERR_USER_ASSIGN_ROLE = "redback:user.role.assign.failure";
|
||||||
|
String ERR_USER_NOT_VALIDATED = "redback:user.not_validated";
|
||||||
|
|
||||||
|
String ERR_LDAP_GENERIC = "redback:ldap.error";
|
||||||
|
String ERR_ROLE_MAPPING = "redback:role.mapping.error";
|
||||||
|
String ERR_ROLE_MAPPING_NOT_FOUND = "redback:role.mapping.not_found";
|
||||||
|
|
||||||
|
String ERR_AUTH_BAD_CODE = "redback:auth.bad_authorization_code";
|
||||||
|
String ERR_AUTH_INVALID_CREDENTIALS = "redback:auth.invalid_credentials";
|
||||||
|
String ERR_AUTH_FAIL_MSG = "redback:auth.fail";
|
||||||
|
String ERR_AUTH_ACCOUNT_LOCKED = "redback:auth.account_locked";
|
||||||
|
String ERR_AUTH_PASSWORD_CHANGE_REQUIRED = "redback:auth.password_change_required";
|
||||||
|
String ERR_AUTH_USERMANAGER_FAIL = "redback:auth.usermanager_error";
|
||||||
|
String ERR_AUTH_UNSUPPORTED_GRANT_TYPE = "redback:auth.unsupported_grant";
|
||||||
|
String ERR_AUTH_INVALID_TOKEN = "redback:auth.invalid_token";
|
||||||
|
String ERR_AUTH_UNAUTHORIZED_REQUEST = "redback:auth.unauthorized_request";
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,10 @@ public class ErrorMessage
|
||||||
this.args = args;
|
this.args = args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ErrorMessage of(String errorKey, String... args) {
|
||||||
|
return new ErrorMessage( errorKey, args );
|
||||||
|
}
|
||||||
|
|
||||||
public String getErrorKey()
|
public String getErrorKey()
|
||||||
{
|
{
|
||||||
return errorKey;
|
return errorKey;
|
||||||
|
|
|
@ -31,11 +31,11 @@ import org.apache.archiva.redback.policy.AccountLockedException;
|
||||||
import org.apache.archiva.redback.policy.MustChangePasswordException;
|
import org.apache.archiva.redback.policy.MustChangePasswordException;
|
||||||
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
|
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
|
||||||
import org.apache.archiva.redback.rest.api.model.GrantType;
|
import org.apache.archiva.redback.rest.api.model.GrantType;
|
||||||
import org.apache.archiva.redback.rest.api.model.v2.PingResult;
|
|
||||||
import org.apache.archiva.redback.rest.api.model.v2.TokenRequest;
|
|
||||||
import org.apache.archiva.redback.rest.api.model.TokenResponse;
|
import org.apache.archiva.redback.rest.api.model.TokenResponse;
|
||||||
import org.apache.archiva.redback.rest.api.model.User;
|
import org.apache.archiva.redback.rest.api.model.User;
|
||||||
import org.apache.archiva.redback.rest.api.model.UserLogin;
|
import org.apache.archiva.redback.rest.api.model.UserLogin;
|
||||||
|
import org.apache.archiva.redback.rest.api.model.v2.PingResult;
|
||||||
|
import org.apache.archiva.redback.rest.api.model.v2.TokenRequest;
|
||||||
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
|
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
|
||||||
import org.apache.archiva.redback.rest.api.services.v2.AuthenticationService;
|
import org.apache.archiva.redback.rest.api.services.v2.AuthenticationService;
|
||||||
import org.apache.archiva.redback.rest.services.interceptors.RedbackPrincipal;
|
import org.apache.archiva.redback.rest.services.interceptors.RedbackPrincipal;
|
||||||
|
@ -56,9 +56,10 @@ import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.SecurityContext;
|
import javax.ws.rs.core.SecurityContext;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.apache.archiva.redback.rest.api.Constants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Authentication service provides REST methods for authentication and verification.
|
* Authentication service provides REST methods for authentication and verification.
|
||||||
|
@ -127,7 +128,7 @@ public class DefaultAuthenticationService
|
||||||
throws RedbackServiceException
|
throws RedbackServiceException
|
||||||
{
|
{
|
||||||
if (!GrantType.AUTHORIZATION_CODE.equals(loginRequest.getGrantType())) {
|
if (!GrantType.AUTHORIZATION_CODE.equals(loginRequest.getGrantType())) {
|
||||||
throw new RedbackServiceException( "redback:bad_authorization_code", Response.Status.FORBIDDEN.getStatusCode( ) );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_AUTH_BAD_CODE ), Response.Status.FORBIDDEN.getStatusCode( ) );
|
||||||
}
|
}
|
||||||
String userName = loginRequest.getUserId(), password = loginRequest.getPassword();
|
String userName = loginRequest.getUserId(), password = loginRequest.getPassword();
|
||||||
PasswordBasedAuthenticationDataSource authDataSource =
|
PasswordBasedAuthenticationDataSource authDataSource =
|
||||||
|
@ -146,7 +147,7 @@ public class DefaultAuthenticationService
|
||||||
if ( !user.isValidated() )
|
if ( !user.isValidated() )
|
||||||
{
|
{
|
||||||
log.info( "user {} not validated", user.getUsername() );
|
log.info( "user {} not validated", user.getUsername() );
|
||||||
throw new RedbackServiceException( "redback:user-not-validated", Response.Status.FORBIDDEN.getStatusCode() );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_USER_NOT_VALIDATED, user.getUsername() ), Response.Status.FORBIDDEN.getStatusCode() );
|
||||||
}
|
}
|
||||||
// Stateless services no session
|
// Stateless services no session
|
||||||
// httpAuthenticator.authenticate( authDataSource, httpServletRequest.getSession( true ) );
|
// httpAuthenticator.authenticate( authDataSource, httpServletRequest.getSession( true ) );
|
||||||
|
@ -162,45 +163,43 @@ public class DefaultAuthenticationService
|
||||||
{
|
{
|
||||||
if ( authenticationFailureCause.getCause() == AuthenticationConstants.AUTHN_NO_SUCH_USER )
|
if ( authenticationFailureCause.getCause() == AuthenticationConstants.AUTHN_NO_SUCH_USER )
|
||||||
{
|
{
|
||||||
errorMessages.add( new ErrorMessage( "redback:incorrect.username.password" ) );
|
errorMessages.add( ErrorMessage.of( ERR_AUTH_INVALID_CREDENTIALS ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
errorMessages.add( new ErrorMessage().message( "redback:"+authenticationFailureCause.getMessage() ) );
|
errorMessages.add( ErrorMessage.of( ERR_AUTH_FAIL_MSG, authenticationFailureCause.getMessage() ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
response.setHeader( "WWW-Authenticate", "redback-login realm="+httpServletRequest.getRemoteHost() );
|
response.setHeader( "WWW-Authenticate", "redback-login realm="+httpServletRequest.getRemoteHost() );
|
||||||
throw new RedbackServiceException( errorMessages , Response.Status.UNAUTHORIZED.getStatusCode());
|
throw new RedbackServiceException( errorMessages , Response.Status.UNAUTHORIZED.getStatusCode());
|
||||||
}
|
}
|
||||||
response.setHeader( "WWW-Authenticate", "redback-login realm="+httpServletRequest.getRemoteHost() );
|
response.setHeader( "WWW-Authenticate", "redback-login realm="+httpServletRequest.getRemoteHost() );
|
||||||
throw new RedbackServiceException( "redback:login-failed", Response.Status.UNAUTHORIZED.getStatusCode() );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_AUTH_FAIL_MSG ), Response.Status.UNAUTHORIZED.getStatusCode() );
|
||||||
}
|
}
|
||||||
|
|
||||||
catch ( AuthenticationException e )
|
catch ( AuthenticationException e )
|
||||||
{
|
{
|
||||||
log.debug( "Authentication error: {}", e.getMessage( ), e );
|
log.debug( "Authentication error: {}", e.getMessage( ), e );
|
||||||
throw new RedbackServiceException( "redback:login-failed", Response.Status.UNAUTHORIZED.getStatusCode() );
|
throw new RedbackServiceException(ErrorMessage.of( ERR_AUTH_FAIL_MSG ), Response.Status.UNAUTHORIZED.getStatusCode() );
|
||||||
}
|
}
|
||||||
catch ( UserNotFoundException e )
|
catch ( UserNotFoundException e )
|
||||||
{
|
{
|
||||||
log.debug( "User not found: {}", e.getMessage( ), e );
|
log.debug( "User not found: {}", e.getMessage( ), e );
|
||||||
throw new RedbackServiceException( "redback:login-failed", Response.Status.UNAUTHORIZED.getStatusCode() );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_AUTH_INVALID_CREDENTIALS ), Response.Status.UNAUTHORIZED.getStatusCode() );
|
||||||
}
|
}
|
||||||
catch (AccountLockedException e) {
|
catch (AccountLockedException e) {
|
||||||
log.info( "Account locked: {}", e.getMessage( ), e );
|
log.info( "Account locked: {}", e.getMessage( ), e );
|
||||||
throw new RedbackServiceException( "redback:account-locked", Response.Status.FORBIDDEN.getStatusCode() );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_AUTH_ACCOUNT_LOCKED ), Response.Status.FORBIDDEN.getStatusCode() );
|
||||||
}
|
}
|
||||||
catch ( MustChangePasswordException e )
|
catch ( MustChangePasswordException e )
|
||||||
{
|
{
|
||||||
log.debug( "Password change required: {}", e.getMessage( ), e );
|
log.debug( "Password change required: {}", e.getMessage( ), e );
|
||||||
throw new RedbackServiceException( "redback:password-change-required", Response.Status.FORBIDDEN.getStatusCode( ) );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_AUTH_PASSWORD_CHANGE_REQUIRED ), Response.Status.FORBIDDEN.getStatusCode( ) );
|
||||||
}
|
}
|
||||||
catch ( UserManagerException e )
|
catch ( UserManagerException e )
|
||||||
{
|
{
|
||||||
log.warn( "UserManagerException: {}", e.getMessage() );
|
log.warn( "UserManagerException: {}", e.getMessage() );
|
||||||
List<ErrorMessage> errorMessages =
|
throw new RedbackServiceException( ErrorMessage.of( ERR_AUTH_USERMANAGER_FAIL, e.getMessage( ) ) );
|
||||||
Arrays.asList( new ErrorMessage().message( "UserManagerException: " + e.getMessage() ) );
|
|
||||||
throw new RedbackServiceException( errorMessages );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -210,7 +209,7 @@ public class DefaultAuthenticationService
|
||||||
{
|
{
|
||||||
if (!GrantType.REFRESH_TOKEN.equals(request.getGrantType())) {
|
if (!GrantType.REFRESH_TOKEN.equals(request.getGrantType())) {
|
||||||
log.debug( "Bad grant type {}, expected: refresh_token", request.getGrantType( ).name( ).toLowerCase( ) );
|
log.debug( "Bad grant type {}, expected: refresh_token", request.getGrantType( ).name( ).toLowerCase( ) );
|
||||||
throw new RedbackServiceException( "redback:bad_grant", Response.Status.FORBIDDEN.getStatusCode( ) );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_AUTH_UNSUPPORTED_GRANT_TYPE, request.getGrantType().getLabel() ), Response.Status.FORBIDDEN.getStatusCode( ) );
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -222,7 +221,7 @@ public class DefaultAuthenticationService
|
||||||
}
|
}
|
||||||
catch ( TokenAuthenticationException e )
|
catch ( TokenAuthenticationException e )
|
||||||
{
|
{
|
||||||
throw new RedbackServiceException( e.getError( ).getError( ), Response.Status.UNAUTHORIZED.getStatusCode( ) );
|
throw new RedbackServiceException( ErrorMessage.of(ERR_AUTH_INVALID_TOKEN, e.getError( ).getError( )), Response.Status.UNAUTHORIZED.getStatusCode( ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +234,7 @@ public class DefaultAuthenticationService
|
||||||
{
|
{
|
||||||
return buildRestUser( pri.getUser( ) );
|
return buildRestUser( pri.getUser( ) );
|
||||||
} else {
|
} else {
|
||||||
throw new RedbackServiceException( "redback:not_authenticated", Response.Status.UNAUTHORIZED.getStatusCode( ) );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_AUTH_UNAUTHORIZED_REQUEST ), Response.Status.UNAUTHORIZED.getStatusCode( ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.apache.archiva.redback.common.ldap.role.LdapGroup;
|
||||||
import org.apache.archiva.redback.common.ldap.role.LdapRoleMapper;
|
import org.apache.archiva.redback.common.ldap.role.LdapRoleMapper;
|
||||||
import org.apache.archiva.redback.common.ldap.role.LdapRoleMapperConfiguration;
|
import org.apache.archiva.redback.common.ldap.role.LdapRoleMapperConfiguration;
|
||||||
import org.apache.archiva.redback.rest.api.model.ActionStatus;
|
import org.apache.archiva.redback.rest.api.model.ActionStatus;
|
||||||
|
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
|
||||||
import org.apache.archiva.redback.rest.api.model.Group;
|
import org.apache.archiva.redback.rest.api.model.Group;
|
||||||
import org.apache.archiva.redback.rest.api.model.v2.GroupMapping;
|
import org.apache.archiva.redback.rest.api.model.v2.GroupMapping;
|
||||||
import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
|
import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
|
||||||
|
@ -51,6 +52,8 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.apache.archiva.redback.rest.api.Constants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* LDAP implementation of the group service
|
* LDAP implementation of the group service
|
||||||
|
@ -106,10 +109,13 @@ public class DefaultGroupService
|
||||||
List<LdapGroup> groups = ldapRoleMapper.getAllGroupObjects( context );
|
List<LdapGroup> groups = ldapRoleMapper.getAllGroupObjects( context );
|
||||||
return PagedResult.of( groups.size( ), offset, limit, groups.stream( ).skip( offset ).limit( limit ).map( DefaultGroupService::getGroupFromLdap ).collect( Collectors.toList( ) ) );
|
return PagedResult.of( groups.size( ), offset, limit, groups.stream( ).skip( offset ).limit( limit ).map( DefaultGroupService::getGroupFromLdap ).collect( Collectors.toList( ) ) );
|
||||||
}
|
}
|
||||||
catch ( LdapException | MappingException e )
|
catch ( LdapException e )
|
||||||
{
|
{
|
||||||
log.error( e.getMessage(), e );
|
log.error( "LDAP Error {}", e.getMessage(), e );
|
||||||
throw new RedbackServiceException( e.getMessage() );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_LDAP_GENERIC ) );
|
||||||
|
} catch (MappingException e) {
|
||||||
|
log.error( "Mapping Error {}", e.getMessage(), e );
|
||||||
|
throw new RedbackServiceException( ErrorMessage.of( ERR_ROLE_MAPPING, e.getMessage( ) ) );
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -150,7 +156,7 @@ public class DefaultGroupService
|
||||||
catch ( LdapException e )
|
catch ( LdapException e )
|
||||||
{
|
{
|
||||||
log.error( "Could not create ldap connection {}", e.getMessage( ) );
|
log.error( "Could not create ldap connection {}", e.getMessage( ) );
|
||||||
throw new RedbackServiceException( "Error while talking to group registry", 500 );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_LDAP_GENERIC, "Error while talking to group registry"), 500 );
|
||||||
}
|
}
|
||||||
catch ( ObjectNotFoundException e ) {
|
catch ( ObjectNotFoundException e ) {
|
||||||
GroupMapping ldapGroupMapping = new GroupMapping( groupName, "", new ArrayList<>( entry.getValue( ) ) );
|
GroupMapping ldapGroupMapping = new GroupMapping( groupName, "", new ArrayList<>( entry.getValue( ) ) );
|
||||||
|
@ -168,7 +174,7 @@ public class DefaultGroupService
|
||||||
catch ( MappingException e )
|
catch ( MappingException e )
|
||||||
{
|
{
|
||||||
log.error( e.getMessage(), e );
|
log.error( e.getMessage(), e );
|
||||||
throw new RedbackServiceException( e.getMessage() );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_ROLE_MAPPING, e.getMessage( ) ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +195,7 @@ public class DefaultGroupService
|
||||||
catch ( MappingException e )
|
catch ( MappingException e )
|
||||||
{
|
{
|
||||||
log.error( e.getMessage(), e );
|
log.error( e.getMessage(), e );
|
||||||
throw new RedbackServiceException( e.getMessage() );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_ROLE_MAPPING, e.getMessage( ) ) );
|
||||||
}
|
}
|
||||||
return ActionStatus.SUCCESS;
|
return ActionStatus.SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -205,7 +211,7 @@ public class DefaultGroupService
|
||||||
catch ( MappingException e )
|
catch ( MappingException e )
|
||||||
{
|
{
|
||||||
log.error( e.getMessage(), e );
|
log.error( e.getMessage(), e );
|
||||||
throw new RedbackServiceException( e.getMessage() );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_ROLE_MAPPING, e.getMessage( ) ) );
|
||||||
}
|
}
|
||||||
return ActionStatus.SUCCESS;
|
return ActionStatus.SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -219,7 +225,7 @@ public class DefaultGroupService
|
||||||
}
|
}
|
||||||
catch ( MappingException e )
|
catch ( MappingException e )
|
||||||
{
|
{
|
||||||
throw new RedbackServiceException( "Group mapping not found ", 404 );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_ROLE_MAPPING_NOT_FOUND), 404 );
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -230,7 +236,7 @@ public class DefaultGroupService
|
||||||
catch ( MappingException e )
|
catch ( MappingException e )
|
||||||
{
|
{
|
||||||
log.error( "Could not update mapping {}", e.getMessage( ) );
|
log.error( "Could not update mapping {}", e.getMessage( ) );
|
||||||
throw new RedbackServiceException( e.getMessage( ) );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_ROLE_MAPPING, e.getMessage( ) ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,16 +45,16 @@ import org.apache.archiva.redback.rest.api.model.ActionStatus;
|
||||||
import org.apache.archiva.redback.rest.api.model.AvailabilityStatus;
|
import org.apache.archiva.redback.rest.api.model.AvailabilityStatus;
|
||||||
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
|
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
|
||||||
import org.apache.archiva.redback.rest.api.model.Operation;
|
import org.apache.archiva.redback.rest.api.model.Operation;
|
||||||
import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
|
|
||||||
import org.apache.archiva.redback.rest.api.model.PasswordStatus;
|
import org.apache.archiva.redback.rest.api.model.PasswordStatus;
|
||||||
import org.apache.archiva.redback.rest.api.model.Permission;
|
import org.apache.archiva.redback.rest.api.model.Permission;
|
||||||
import org.apache.archiva.redback.rest.api.model.v2.PingResult;
|
|
||||||
import org.apache.archiva.redback.rest.api.model.RegistrationKey;
|
import org.apache.archiva.redback.rest.api.model.RegistrationKey;
|
||||||
import org.apache.archiva.redback.rest.api.model.ResetPasswordRequest;
|
import org.apache.archiva.redback.rest.api.model.ResetPasswordRequest;
|
||||||
import org.apache.archiva.redback.rest.api.model.Resource;
|
import org.apache.archiva.redback.rest.api.model.Resource;
|
||||||
|
import org.apache.archiva.redback.rest.api.model.VerificationStatus;
|
||||||
|
import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
|
||||||
|
import org.apache.archiva.redback.rest.api.model.v2.PingResult;
|
||||||
import org.apache.archiva.redback.rest.api.model.v2.User;
|
import org.apache.archiva.redback.rest.api.model.v2.User;
|
||||||
import org.apache.archiva.redback.rest.api.model.v2.UserRegistrationRequest;
|
import org.apache.archiva.redback.rest.api.model.v2.UserRegistrationRequest;
|
||||||
import org.apache.archiva.redback.rest.api.model.VerificationStatus;
|
|
||||||
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
|
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
|
||||||
import org.apache.archiva.redback.rest.api.services.v2.UserService;
|
import org.apache.archiva.redback.rest.api.services.v2.UserService;
|
||||||
import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal;
|
import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal;
|
||||||
|
@ -77,8 +77,10 @@ import javax.inject.Named;
|
||||||
import javax.mail.internet.AddressException;
|
import javax.mail.internet.AddressException;
|
||||||
import javax.mail.internet.InternetAddress;
|
import javax.mail.internet.InternetAddress;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -86,6 +88,8 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.apache.archiva.redback.rest.api.Constants.*;
|
||||||
|
|
||||||
@Service( "v2.userService#rest" )
|
@Service( "v2.userService#rest" )
|
||||||
public class DefaultUserService
|
public class DefaultUserService
|
||||||
implements UserService
|
implements UserService
|
||||||
|
@ -145,6 +149,12 @@ public class DefaultUserService
|
||||||
@Context
|
@Context
|
||||||
private HttpServletRequest httpServletRequest;
|
private HttpServletRequest httpServletRequest;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
private HttpServletResponse httpServletResponse;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
private UriInfo uriInfo;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DefaultUserService( @Named( value = "userManager#default" ) UserManager userManager,
|
public DefaultUserService( @Named( value = "userManager#default" ) UserManager userManager,
|
||||||
SecuritySystem securitySystem )
|
SecuritySystem securitySystem )
|
||||||
|
@ -164,8 +174,9 @@ public class DefaultUserService
|
||||||
org.apache.archiva.redback.users.User u = userManager.findUser( user.getUserId() );
|
org.apache.archiva.redback.users.User u = userManager.findUser( user.getUserId() );
|
||||||
if ( u != null )
|
if ( u != null )
|
||||||
{
|
{
|
||||||
|
httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder( ).path( u.getUsername( ) ).build( ).toString( ) );
|
||||||
throw new RedbackServiceException(
|
throw new RedbackServiceException(
|
||||||
new ErrorMessage( "user " + user.getUserId() + " already exists" ) );
|
ErrorMessage.of( ERR_USER_EXISTS, user.getUserId() ), 303 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch ( UserNotFoundException e )
|
catch ( UserNotFoundException e )
|
||||||
|
@ -175,23 +186,23 @@ public class DefaultUserService
|
||||||
}
|
}
|
||||||
catch ( UserManagerException e )
|
catch ( UserManagerException e )
|
||||||
{
|
{
|
||||||
throw new RedbackServiceException( new ErrorMessage( e.getMessage() ) );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_UNKNOWN, e.getMessage() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// data validation
|
// data validation
|
||||||
if ( StringUtils.isEmpty( user.getUserId() ) )
|
if ( StringUtils.isEmpty( user.getUserId() ) )
|
||||||
{
|
{
|
||||||
throw new RedbackServiceException( new ErrorMessage( "username cannot be empty" ) );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_USER_ID_EMPTY ), 405 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( StringUtils.isEmpty( user.getFullName() ) )
|
if ( StringUtils.isEmpty( user.getFullName() ) )
|
||||||
{
|
{
|
||||||
throw new RedbackServiceException( new ErrorMessage( "fullName cannot be empty" ) );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_USER_FULL_NAME_EMPTY ), 405 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( StringUtils.isEmpty( user.getEmail() ) )
|
if ( StringUtils.isEmpty( user.getEmail() ) )
|
||||||
{
|
{
|
||||||
throw new RedbackServiceException( new ErrorMessage( "email cannot be empty" ) );
|
throw new RedbackServiceException( ErrorMessage.of( ERR_USER_EMAIL_EMPTY ), 405 );
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -220,15 +231,17 @@ public class DefaultUserService
|
||||||
}
|
}
|
||||||
|
|
||||||
roleManager.assignRole( RedbackRoleConstants.REGISTERED_USER_ROLE_ID, u.getUsername() );
|
roleManager.assignRole( RedbackRoleConstants.REGISTERED_USER_ROLE_ID, u.getUsername() );
|
||||||
|
httpServletResponse.setStatus( 201 );
|
||||||
|
httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder().path( user.getUserId() ).build( ).toString() );
|
||||||
}
|
}
|
||||||
catch ( RoleManagerException rpe )
|
catch ( RoleManagerException rpe )
|
||||||
{
|
{
|
||||||
log.error( "RoleProfile Error: {}", rpe.getMessage(), rpe );
|
log.error( "RoleProfile Error: {}", rpe.getMessage(), rpe );
|
||||||
throw new RedbackServiceException( new ErrorMessage( "assign.role.failure", null ) );
|
throw new RedbackServiceException( ErrorMessage.of(ERR_USER_ASSIGN_ROLE ) );
|
||||||
}
|
}
|
||||||
catch ( UserManagerException e )
|
catch ( UserManagerException e )
|
||||||
{
|
{
|
||||||
throw new RedbackServiceException( new ErrorMessage( e.getMessage() ) );
|
throw new RedbackServiceException( ErrorMessage.of(ERR_UNKNOWN, e.getMessage() ) );
|
||||||
}
|
}
|
||||||
return ActionStatus.SUCCESS;
|
return ActionStatus.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -382,6 +382,19 @@ public abstract class AbstractNativeRestServices
|
||||||
this.adminRefreshToken = result.body( ).jsonPath( ).getString( "refresh_token" );
|
this.adminRefreshToken = result.body( ).jsonPath( ).getString( "refresh_token" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String getUserToken(String userId, String password) {
|
||||||
|
Map<String, Object> jsonAsMap = new HashMap<>();
|
||||||
|
jsonAsMap.put( "grant_type", "authorization_code" );
|
||||||
|
jsonAsMap.put("user_id", userId);
|
||||||
|
jsonAsMap.put("password", password );
|
||||||
|
Response result = given( ).spec( getAuthRequestSpecBuilder().build() )
|
||||||
|
.contentType( JSON )
|
||||||
|
.body( jsonAsMap )
|
||||||
|
.when( ).post( "/authenticate").prettyPeek().then( ).statusCode( 200 )
|
||||||
|
.extract( ).response( );
|
||||||
|
result.getBody( ).prettyPrint( );
|
||||||
|
return result.body( ).jsonPath( ).getString( "access_token" );
|
||||||
|
}
|
||||||
protected String getAdminToken() {
|
protected String getAdminToken() {
|
||||||
if (this.adminToken == null) {
|
if (this.adminToken == null) {
|
||||||
initAdminToken();
|
initAdminToken();
|
||||||
|
@ -389,6 +402,7 @@ public abstract class AbstractNativeRestServices
|
||||||
return this.adminToken;
|
return this.adminToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected String getAdminRefreshToken() {
|
protected String getAdminRefreshToken() {
|
||||||
if (this.adminRefreshToken == null) {
|
if (this.adminRefreshToken == null) {
|
||||||
initAdminToken();
|
initAdminToken();
|
||||||
|
|
|
@ -19,22 +19,36 @@ package org.apache.archiva.redback.rest.services.v2;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import io.restassured.response.Response;
|
import io.restassured.response.Response;
|
||||||
import org.apache.archiva.redback.rest.api.model.Group;
|
import org.apache.archiva.redback.rest.api.model.v2.User;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.MethodOrderer;
|
||||||
|
import org.junit.jupiter.api.Tag;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.TestInstance;
|
||||||
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.Map;
|
||||||
|
|
||||||
import static io.restassured.RestAssured.given;
|
import static io.restassured.RestAssured.given;
|
||||||
import static io.restassured.http.ContentType.JSON;
|
import static io.restassured.http.ContentType.JSON;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Martin Stockhammer <martin_s@apache.org>
|
* @author Martin Stockhammer <martin_s@apache.org>
|
||||||
*/
|
*/
|
||||||
|
@ExtendWith( SpringExtension.class )
|
||||||
|
@ContextConfiguration(
|
||||||
|
locations = {"classpath:/ldap-spring-test.xml"} )
|
||||||
|
@TestInstance( TestInstance.Lifecycle.PER_CLASS )
|
||||||
|
@Tag("rest-native")
|
||||||
|
@TestMethodOrder( MethodOrderer.Random.class )
|
||||||
public class NativeUserServiceTest extends AbstractNativeRestServices
|
public class NativeUserServiceTest extends AbstractNativeRestServices
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
|
@ -55,21 +69,166 @@ public class NativeUserServiceTest extends AbstractNativeRestServices
|
||||||
super.shutdownNative();
|
super.shutdownNative();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
@Test
|
||||||
// void getGroups() {
|
void getUsers() {
|
||||||
// String token = getAdminToken( );
|
String token = getAdminToken( );
|
||||||
// Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ).when( )
|
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
|
||||||
// .get( ).then( ).statusCode( 200 ).extract( ).response( );
|
.when( ).get( ).then( ).statusCode( 200 ).extract( ).response( );
|
||||||
// assertNotNull( response );
|
assertNotNull( response );
|
||||||
// List<Group> data = response.body( ).jsonPath( ).getList( "data", Group.class );
|
List<User> userData = response.body( ).jsonPath( ).getList( "data", User.class );
|
||||||
// assertNotNull( data );
|
assertNotNull( userData );
|
||||||
// assertEquals( Integer.valueOf( 0 ), response.body( ).jsonPath( ).get( "pagination.offset" ) );
|
assertEquals( 2, userData.size( ) );
|
||||||
// assertEquals( Integer.valueOf( 1000 ), response.body( ).jsonPath( ).get( "pagination.limit" ) );
|
assertEquals( Integer.valueOf( 0 ), response.body( ).jsonPath( ).get( "pagination.offset" ) );
|
||||||
// assertEquals( Integer.valueOf( 6 ), response.body( ).jsonPath( ).get( "pagination.totalCount" ) );
|
assertEquals( Integer.valueOf( 1000 ), response.body( ).jsonPath( ).get( "pagination.limit" ) );
|
||||||
// assertEquals( 6, data.size( ) );
|
assertEquals( Integer.valueOf( 2 ), response.body( ).jsonPath( ).get( "pagination.totalCount" ) );
|
||||||
// String[] values = data.stream( ).map( ldapInfo -> ldapInfo.getName( ) ).sorted( ).collect( Collectors.toList( ) ).toArray( new String[0] );
|
}
|
||||||
// assertArrayEquals( getTestGroupList( ).toArray( new String[0] ), values );
|
|
||||||
// assertEquals( "uid=admin," + this.peopleSuffix, data.get( 0 ).getMemberList( ).get( 0 ) );
|
@Test
|
||||||
// }
|
void getUsersWithoutLogin() {
|
||||||
|
given( ).spec( getRequestSpec( ) ).contentType( JSON )
|
||||||
|
.when( ).get( ).then( ).statusCode( 403 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getUser() {
|
||||||
|
String token = getAdminToken( );
|
||||||
|
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
|
||||||
|
.when( ).get( "admin" ).then( ).statusCode( 200 ).extract( ).response( );
|
||||||
|
assertNotNull( response );
|
||||||
|
assertEquals( "jpa:admin", response.body( ).jsonPath( ).get( "id" ) );
|
||||||
|
assertEquals( "admin", response.body( ).jsonPath( ).get( "user_id" ) );
|
||||||
|
assertEquals( "the admin user", response.body( ).jsonPath( ).get( "fullName" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getUserWithoutLogin() {
|
||||||
|
given( ).spec( getRequestSpec( ) ).contentType( JSON )
|
||||||
|
.when( ).get( "admin" ).then( ).statusCode( 403 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createUser() {
|
||||||
|
String token = getAdminToken( );
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Map<String, Object> jsonAsMap = new HashMap<>( );
|
||||||
|
jsonAsMap.put( "user_id", "aragorn" );
|
||||||
|
jsonAsMap.put( "email", "aragorn@lordoftherings.org" );
|
||||||
|
jsonAsMap.put( "fullName", "Aragorn King of Gondor" );
|
||||||
|
jsonAsMap.put( "password", "pAssw0rD" );
|
||||||
|
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
|
||||||
|
.body( jsonAsMap )
|
||||||
|
.when( )
|
||||||
|
.post( )
|
||||||
|
.then( ).statusCode( 201 ).extract( ).response( );
|
||||||
|
assertTrue( response.getHeader( "Location" ).endsWith( "/aragorn" ) );
|
||||||
|
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
|
||||||
|
.when( ).delete( "aragorn").then( ).statusCode( 200 );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createInvalidUser() {
|
||||||
|
String token = getAdminToken( );
|
||||||
|
Map<String, Object> jsonAsMap = new HashMap<>( );
|
||||||
|
jsonAsMap.put( "user_id", "" );
|
||||||
|
jsonAsMap.put( "email", "aragorn@lordoftherings.org" );
|
||||||
|
jsonAsMap.put( "fullName", "Aragorn King of Gondor" );
|
||||||
|
jsonAsMap.put( "password", "pAssw0rD" );
|
||||||
|
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
|
||||||
|
.body( jsonAsMap )
|
||||||
|
.when( )
|
||||||
|
.post( )
|
||||||
|
.then( ).statusCode( 405 ).extract( ).response( );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createUserAndPermissionFail() {
|
||||||
|
String token = getAdminToken( );
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Map<String, Object> jsonAsMap = new HashMap<>( );
|
||||||
|
jsonAsMap.put( "user_id", "aragorn" );
|
||||||
|
jsonAsMap.put( "email", "aragorn@lordoftherings.org" );
|
||||||
|
jsonAsMap.put( "fullName", "Aragorn King of Gondor" );
|
||||||
|
jsonAsMap.put( "validated", true );
|
||||||
|
jsonAsMap.put( "password", "pAssw0rD" );
|
||||||
|
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
|
||||||
|
.body( jsonAsMap )
|
||||||
|
.when( )
|
||||||
|
.post( )
|
||||||
|
.then( ).statusCode( 201 ).extract( ).response( );
|
||||||
|
assertTrue( response.getHeader( "Location" ).endsWith( "/aragorn" ) );
|
||||||
|
|
||||||
|
String userToken = getUserToken( "aragorn", "pAssw0rD" );
|
||||||
|
|
||||||
|
jsonAsMap = new HashMap<>( );
|
||||||
|
jsonAsMap.put( "user_id", "arwen" );
|
||||||
|
jsonAsMap.put( "email", "arwen@lordoftherings.org" );
|
||||||
|
jsonAsMap.put( "fullName", "Arwen Daughter of Elrond" );
|
||||||
|
jsonAsMap.put( "password", "pAssw0rD" );
|
||||||
|
given( ).spec( getRequestSpec( userToken ) ).contentType( JSON )
|
||||||
|
.body( jsonAsMap )
|
||||||
|
.when( )
|
||||||
|
.post( )
|
||||||
|
.then( ).statusCode( 403 );
|
||||||
|
|
||||||
|
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
|
||||||
|
.when( ).delete( "aragorn").then( ).statusCode( 200 );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createUserExistsAlready() {
|
||||||
|
String token = getAdminToken( );
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Map<String, Object> jsonAsMap = new HashMap<>( );
|
||||||
|
jsonAsMap.put( "user_id", "aragorn" );
|
||||||
|
jsonAsMap.put( "email", "aragorn@lordoftherings.org" );
|
||||||
|
jsonAsMap.put( "fullName", "Aragorn King of Gondor" );
|
||||||
|
jsonAsMap.put( "validated", true );
|
||||||
|
jsonAsMap.put( "password", "pAssw0rD" );
|
||||||
|
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
|
||||||
|
.body( jsonAsMap )
|
||||||
|
.when( )
|
||||||
|
.post( )
|
||||||
|
.then( ).statusCode( 201 ).extract( ).response( );
|
||||||
|
assertTrue( response.getHeader( "Location" ).endsWith( "/aragorn" ) );
|
||||||
|
|
||||||
|
jsonAsMap = new HashMap<>( );
|
||||||
|
jsonAsMap.put( "user_id", "aragorn" );
|
||||||
|
jsonAsMap.put( "email", "aragorn@lordoftherings.org" );
|
||||||
|
jsonAsMap.put( "fullName", "Aragorn King of Gondor" );
|
||||||
|
jsonAsMap.put( "validated", true );
|
||||||
|
jsonAsMap.put( "password", "pAssw0rD" );
|
||||||
|
|
||||||
|
response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
|
||||||
|
.body( jsonAsMap )
|
||||||
|
.when( )
|
||||||
|
.redirects().follow( false ) // Rest assured default is following the 303 redirect
|
||||||
|
.post( )
|
||||||
|
.prettyPeek()
|
||||||
|
.peek()
|
||||||
|
.then( ).statusCode( 303 ).extract().response();
|
||||||
|
assertTrue( response.getHeader( "Location" ).endsWith( "/aragorn" ) );
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
|
||||||
|
.when( ).delete( "aragorn").then( ).statusCode( 200 );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue