diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/Constants.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/Constants.java index c280e55a..54a03e82 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/Constants.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/Constants.java @@ -29,6 +29,7 @@ public interface Constants String ERR_USERMANAGER_FAIL = "redback:usermanager_error"; String ERR_ROLEMANAGER_FAIL = "redback:rolemanager_error"; String ERR_RBACMANAGER_FAIL = "redback:rbacmanager_error"; + String ERR_KEYMANAGER_FAIL = "reback:keymanager_error"; String ERR_INVALID_POST_DATA = "redback:invalid_post_data"; String ERR_USER_EXISTS = "redback:user.exists"; @@ -57,8 +58,14 @@ public interface Constants String ERR_AUTH_INVALID_TOKEN = "redback:auth.invalid_token"; String ERR_AUTH_UNAUTHORIZED_REQUEST = "redback:auth.unauthorized_request"; + String ERR_PASSWD_RESET_FAILED = "redback:passwd.reset.fail"; + String ERR_USER_BAD_PASSWORD = "redback:user.bad.password"; + String ERR_REGISTRATION_KEY_INVALID = "redback:registration.key.invalid"; + String ERR_REGISTRATION_USER_VALIDATED = "redback:registration.user.validated"; + String ERR_REGISTRATION_ROLE_ASSIGNMENT_FAILED = "redback:registration.role.assignment.failed"; + diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/UserService.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/UserService.java index e87d77d4..d6d1c275 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/UserService.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/UserService.java @@ -488,7 +488,7 @@ public interface UserService @Path( "{userId}/register/{key}/validate" ) - @GET + @POST @Produces( {MediaType.APPLICATION_JSON} ) @RedbackAuthorization( noRestriction = true, noPermission = true ) @io.swagger.v3.oas.annotations.Operation( summary = "Validate the user registration for the given userid by checking the provided key.", @@ -496,7 +496,7 @@ public interface UserService @ApiResponse( responseCode = "200", description = "If the verification was successful" ), - @ApiResponse( responseCode = "404", description = "No user registration was found for the given id and key" ), + @ApiResponse( responseCode = "404", description = "No user registration was found for the given id and key" ) } ) VerificationStatus validateUserRegistration( @PathParam( "userId" ) String userId, @PathParam( "key" ) String key ) diff --git a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultUserService.java b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultUserService.java index 40d50b7c..d7c64b3d 100644 --- a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultUserService.java +++ b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultUserService.java @@ -475,7 +475,7 @@ public class DefaultUserService } catch ( UserManagerException e ) { - throw new RedbackServiceException( new ErrorMessage( e.getMessage() ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_USERMANAGER_FAIL, e.getMessage() ), 400 ); } } @@ -560,11 +560,11 @@ public class DefaultUserService } catch ( RoleManagerException e ) { - throw new RedbackServiceException( ErrorMessage.of( ERR_ROLEMANAGER_FAIL, e.getMessage( ) ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_ROLEMANAGER_FAIL, e.getMessage( ) ), 400 ); } catch ( UserManagerException e ) { - throw new RedbackServiceException( ErrorMessage.of( ERR_USERMANAGER_FAIL, e.getMessage() ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_USERMANAGER_FAIL, e.getMessage() ), 400 ); } httpServletResponse.setStatus( 201 ); httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePath().toString() ); @@ -597,7 +597,7 @@ public class DefaultUserService { return new AvailabilityStatus( false ); } - throw new RedbackServiceException( ErrorMessage.of( ERR_USERMANAGER_FAIL, e.getMessage() ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_USERMANAGER_FAIL, e.getMessage() ), 400 ); } return new AvailabilityStatus( false ); } @@ -631,16 +631,16 @@ public class DefaultUserService catch ( UserNotFoundException e ) { log.info( "Password Reset on non-existant user [{}].", username ); - throw new RedbackServiceException( new ErrorMessage( ERR_USER_NOT_FOUND ), 404 ); + throw new RedbackServiceException( ErrorMessage.of( ERR_USER_NOT_FOUND, userId ), 404 ); } catch ( KeyManagerException e ) { log.info( "Unable to issue password reset.", e ); - throw new RedbackServiceException( new ErrorMessage( "password.reset.email.generation.failure" ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_PASSWD_RESET_FAILED, e.getMessage() ), 400 ); } catch ( UserManagerException e ) { - throw new RedbackServiceException( new ErrorMessage( e.getMessage() ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_USERMANAGER_FAIL, e.getMessage() ), 400 ); } return ActionStatus.SUCCESS; @@ -653,7 +653,7 @@ public class DefaultUserService User user = userRegistrationRequest.getUser(); if ( user == null ) { - throw new RedbackServiceException( new ErrorMessage( "invalid.user.credentials", null ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_USER_NOT_FOUND, userId ), 404 ); } @@ -693,11 +693,11 @@ public class DefaultUserService catch ( RoleManagerException rpe ) { log.error( "RoleProfile Error: {}", rpe.getMessage(), rpe ); - throw new RedbackServiceException( new ErrorMessage( "assign.role.failure", null ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_REGISTRATION_ROLE_ASSIGNMENT_FAILED, rpe.getMessage( ) ), 400 ); } catch ( UserManagerException e ) { - throw new RedbackServiceException( new ErrorMessage( e.getMessage() ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_USERMANAGER_FAIL, e.getMessage() ), 400 ); } if ( emailValidationRequired ) @@ -728,11 +728,11 @@ public class DefaultUserService catch ( KeyManagerException e ) { log.error( "Unable to register a new user.", e ); - throw new RedbackServiceException( new ErrorMessage( "cannot.register.user", null ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_KEYMANAGER_FAIL, e.getMessage() ), 400 ); } catch ( UserManagerException e ) { - throw new RedbackServiceException( new ErrorMessage( e.getMessage() ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_USERMANAGER_FAIL, e.getMessage() ), 400 ); } finally { @@ -748,7 +748,7 @@ public class DefaultUserService } catch ( UserManagerException e ) { - throw new RedbackServiceException( new ErrorMessage( e.getMessage() ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_USERMANAGER_FAIL, e.getMessage() ), 400 ); } } @@ -809,11 +809,14 @@ public class DefaultUserService org.apache.archiva.redback.users.User user = securitySystem.getUserManager().findUser( authkey.getForPrincipal() ); + if (user.isValidated()) { + throw new RedbackServiceException( ErrorMessage.of( ERR_REGISTRATION_USER_VALIDATED ), 404 ); + } user.setValidated( true ); user.setLocked( false ); user.setPasswordChangeRequired( true ); user.setEncodedPassword( "" ); - + securitySystem.getUserManager().updateUser( user ); principal = user.getUsername(); TokenBasedAuthenticationDataSource authsource = new TokenBasedAuthenticationDataSource(); @@ -821,42 +824,53 @@ public class DefaultUserService authsource.setToken( authkey.getKey() ); authsource.setEnforcePasswordChange( false ); - securitySystem.getUserManager().updateUser( user ); - VerificationStatus status = new VerificationStatus(false ); SecuritySession authStatus = securitySystem.authenticate( authsource ); if (authStatus.isAuthenticated()) { Token accessToken = jwtAuthenticator.generateToken( principal ); status.setAccessToken( accessToken.getData() ); status.setSuccess( true ); + } else { + user.setValidated( false ); + user.setLocked( true ); + user.setPasswordChangeRequired( false ); + securitySystem.getUserManager().updateUser( user ); } log.info( "account validated for user {}", user.getUsername() ); return status; } - catch ( MustChangePasswordException | AccountLockedException | AuthenticationException e ) + catch ( MustChangePasswordException e ) { - throw new RedbackServiceException( e.getMessage(), Response.Status.FORBIDDEN.getStatusCode() ); + throw new RedbackServiceException( ErrorMessage.of( ERR_AUTH_PASSWORD_CHANGE_REQUIRED ), Response.Status.FORBIDDEN.getStatusCode() ); + } + catch ( AccountLockedException e ) + { + throw new RedbackServiceException( ErrorMessage.of( ERR_AUTH_ACCOUNT_LOCKED ), Response.Status.FORBIDDEN.getStatusCode() ); + } + catch ( AuthenticationException e ) + { + throw new RedbackServiceException( ErrorMessage.of( ERR_AUTH_INVALID_CREDENTIALS ), Response.Status.FORBIDDEN.getStatusCode() ); } catch ( KeyNotFoundException e ) { log.info( "Invalid key requested: {}", key ); - throw new RedbackServiceException( new ErrorMessage( "cannot.find.key" ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_REGISTRATION_KEY_INVALID ), 404 ); } catch ( KeyManagerException e ) { - throw new RedbackServiceException( new ErrorMessage( "cannot.find.key.at.the.momment" ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_KEYMANAGER_FAIL, e.getMessage( ) ), 400 ); } catch ( UserNotFoundException e ) { - throw new RedbackServiceException( new ErrorMessage( "cannot.find.user", new String[]{ principal } ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_USER_NOT_FOUND, principal ), 404 ); } catch ( UserManagerException e ) { - throw new RedbackServiceException( new ErrorMessage( e.getMessage() ) ); + throw new RedbackServiceException( ErrorMessage.of( ERR_USERMANAGER_FAIL, e.getMessage() ), 400 ); } } @@ -915,7 +929,7 @@ public class DefaultUserService catch ( RbacManagerException e ) { log.error( e.getMessage(), e ); - throw new RedbackServiceException( e.getMessage() ); + throw new RedbackServiceException( ErrorMessage.of( ERR_RBACMANAGER_FAIL, e.getMessage() ), 400 ); } } diff --git a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeUserServiceTest.java b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeUserServiceTest.java index 09e051bb..56e24ab2 100644 --- a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeUserServiceTest.java +++ b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeUserServiceTest.java @@ -21,6 +21,8 @@ package org.apache.archiva.redback.rest.services.v2; import io.restassured.response.Response; import org.apache.archiva.redback.rest.api.model.Operation; import org.apache.archiva.redback.rest.api.model.Permission; +import org.apache.archiva.redback.rest.api.model.VerificationStatus; +import org.apache.archiva.redback.rest.api.model.v2.RegistrationKey; import org.apache.archiva.redback.rest.api.model.v2.User; import org.apache.archiva.redback.rest.services.mock.EmailMessage; import org.junit.jupiter.api.AfterAll; @@ -1221,4 +1223,129 @@ public class NativeUserServiceTest extends AbstractNativeRestServices .then( ).statusCode( 200 ); } } + + @Test + void getOwnPermissions( ) + { + String adminToken = getAdminToken( ); + Map 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" ); + given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON ) + .body( jsonAsMap ) + .when( ) + .post( ) + .then( ).statusCode( 201 ); + try + { + + String token = getUserToken( "aragorn", "pAssw0rD" ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "me/permissions" ) + .then( ).statusCode( 200 ).extract( ).response( ); + List result = response.getBody( ).jsonPath( ).getList( "", Permission.class ); + assertNotNull( result ); + assertEquals( 2, result.size( ) ); + assertTrue( result.stream( ).anyMatch( permission -> permission.getName( ).equals( "Edit User Data by Username" ) ) ); + assertTrue( result.stream( ).anyMatch( permission -> permission.getName( ).equals( "View User Data by Username" ) ) ); + } + finally + { + given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON ) + .delete( "aragorn" ) + .then( ).statusCode( 200 ); + } + } + + @Test + void getOwnOperations( ) + { + String adminToken = getAdminToken( ); + Map 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" ); + given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON ) + .body( jsonAsMap ) + .when( ) + .post( ) + .then( ).statusCode( 201 ); + try + { + + String token = getUserToken( "aragorn", "pAssw0rD" ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "me/operations" ) + .prettyPeek( ) + .then( ).statusCode( 200 ).extract( ).response( ); + List result = response.getBody( ).jsonPath( ).getList( "", Operation.class ); + assertNotNull( result ); + assertEquals( 2, result.size( ) ); + assertTrue( result.stream( ).anyMatch( operation -> operation.getName( ).equals( "user-management-user-edit" ) ) ); + assertTrue( result.stream( ).anyMatch( operation -> operation.getName( ).equals( "user-management-user-view" ) ) ); + + + + } + finally + { + given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON ) + .delete( "aragorn" ) + .then( ).statusCode( 200 ); + } + } + + @Test + void validateUserRegistration() { + String adminToken = getAdminToken( ); + + Map userMap = new HashMap<>( ); + Map requestMap = new HashMap<>( ); + + + userMap.put( "user_id", "bilbo" ); + userMap.put( "email", "bilbo@lordoftherings.org" ); + userMap.put( "fullName", "Bilbo Beutlin" ); + userMap.put( "validated", true ); + userMap.put( "password", "pAssw0rD" ); + userMap.put( "confirmPassword", "pAssw0rD" ); + requestMap.put( "user", userMap ); + requestMap.put( "applicationUrl", "http://localhost" ); + + try + { + Response response = given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON ) + .body( requestMap ) + .when( ) + .post( "bilbo/register" ) + .then( ).statusCode( 200 ).extract( ).response( ); + RegistrationKey key = response.getBody( ).jsonPath( ).getObject( "", RegistrationKey.class ); + assertNotNull( key ); + assertNotNull( key.getKey( ) ); + + response = given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON ) + .body( requestMap ) + .when( ) + .post( "bilbo/register/"+key.getKey()+"/validate" ) + .then( ).statusCode( 200 ).extract( ).response( ); + + assertNotNull( response ); + VerificationStatus verificationStatus = response.getBody( ).jsonPath( ).getObject( "", VerificationStatus.class ); + assertNotNull( verificationStatus ); + assertTrue( verificationStatus.isSuccess( ) ); + + } finally + { + given( ).spec( getRequestSpec( adminToken ) ).contentType( JSON ) + .delete( "bilbo" ) + .then( ).statusCode( 200 ); + } + } }