Updating Role REST v2 service
diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/Permission.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/Permission.java
index daf5f65..3900bc5 100644
--- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/Permission.java
+++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/Permission.java
@@ -60,6 +60,10 @@
this.permanent = permission.isPermanent();
}
+ public static Permission of( org.apache.archiva.redback.rbac.Permission perm ) {
+ return new Permission( perm );
+ }
+
@Schema(name="name", description = "The identifier of the permission")
public String getName()
{
diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/RoleInfo.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/RoleInfo.java
index 01a2698..11ead1a 100644
--- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/RoleInfo.java
+++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/RoleInfo.java
@@ -28,6 +28,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.stream.Collectors;
/**
* Result object for role information.
@@ -36,7 +37,7 @@
* @since 3.0
*/
@XmlRootElement( name = "role" )
-@Schema(name="RoleInfo",description = "Information about role")
+@Schema(name="RoleInfo",description = "Information about role.")
public class RoleInfo extends BaseRoleInfo
implements Serializable
{
@@ -57,26 +58,6 @@
*/
private List<String> parentRoleIds = new ArrayList<>(0);
- /**
- * The ids of all the assigned users.
- */
- protected List<BaseUserInfo> assignedUsers = new ArrayList<>( 0 );
-
- @Schema( description = "List of user ids that are assigned to this role.")
- public List<BaseUserInfo> getAssignedUsers( )
- {
- return assignedUsers;
- }
-
- public void setAssignedUsers( List<BaseUserInfo> assignedUsers )
- {
- this.assignedUsers = assignedUsers;
- }
-
- public void addAssignedUser( BaseUserInfo id) {
- this.assignedUsers.add( id );
- }
-
public RoleInfo()
{
// no op
@@ -85,6 +66,12 @@
public static RoleInfo of( Role rbacRole) {
RoleInfo role = BaseRoleInfo.of( rbacRole, new RoleInfo( ) );
+ if(rbacRole.getPermissions()!=null)
+ {
+ role.permissions = rbacRole.getPermissions( ).stream( ).map( rbacPerm ->
+ Permission.of( rbacPerm )
+ ).collect( Collectors.toList( ) );
+ }
return role;
}
@@ -151,7 +138,6 @@
sb.append( ", childRoleNames=" ).append( childRoleIds );
sb.append( ", permissions=" ).append( permissions );
sb.append( ", parentRoleNames=" ).append( parentRoleIds );
- sb.append( ", assignedUsers=" ).append( assignedUsers );
sb.append( ", permanent=" ).append( isPermanent( ) );
sb.append( ", modelId='" ).append( modelId ).append( '\'' );
sb.append( ", resource='" ).append( resource ).append( '\'' );
diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/RoleService.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/RoleService.java
index c88bc61..3aec8ba 100644
--- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/RoleService.java
+++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/RoleService.java
@@ -33,6 +33,7 @@
import org.apache.archiva.redback.rest.api.model.v2.Role;
import org.apache.archiva.redback.rest.api.model.v2.RoleInfo;
import org.apache.archiva.redback.rest.api.model.v2.RoleTemplate;
+import org.apache.archiva.redback.rest.api.model.v2.UserInfo;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import javax.ws.rs.DELETE;
@@ -99,7 +100,7 @@
@GET
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
- @Operation( summary = "Returns information about a specific role. Use HTTP HEAD method for checking, if the resource exists.",
+ @Operation( summary = "Returns the definition about a specific role.",
security = {
@SecurityRequirement(
name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION
@@ -124,7 +125,7 @@
@HEAD
@Produces( { APPLICATION_JSON } )
@RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
- @Operation( summary = "Returns information about a specific role. Use HTTP HEAD method for checking, if the resource exists.",
+ @Operation( summary = "Checks, if the role with the given id exists.",
security = {
@SecurityRequirement(
name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION
@@ -273,32 +274,6 @@
throws RedbackServiceException;
- /**
- * Assigns the role indicated by the roleId to the given principal
- *
- * @param roleId
- * @param userId
- */
- @Path( "{roleId}/user/{userId}" )
- @PUT
- @Produces( { APPLICATION_JSON } )
- @RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
- @Operation( summary = "Assigns a role to a given user",
- security = {
- @SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
- },
- responses = {
- @ApiResponse( responseCode = "200",
- description = "If the role was assigned"
- ),
- @ApiResponse( responseCode = "404", description = "Role does not exist",
- content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
- @ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for role assignment.",
- content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
- }
- )
- RoleInfo assignRole( @PathParam( "roleId" ) String roleId, @PathParam( "userId" ) String userId )
- throws RedbackServiceException;
/**
* Assigns the templated role indicated by the templateId
@@ -333,10 +308,37 @@
throws RedbackServiceException;
/**
- * Unassigns the role indicated by the role id from the given principal
+ * Assigns the role indicated by the roleId to the given principal
*
* @param roleId
* @param userId
+ */
+ @Path( "{roleId}/user/{userId}" )
+ @PUT
+ @Produces( { APPLICATION_JSON } )
+ @RedbackAuthorization( permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
+ @Operation( summary = "Assigns a role to a given user",
+ security = {
+ @SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
+ },
+ responses = {
+ @ApiResponse( responseCode = "200",
+ description = "If the role was assigned"
+ ),
+ @ApiResponse( responseCode = "404", description = "Role does not exist",
+ content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
+ @ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for role assignment.",
+ content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
+ }
+ )
+ RoleInfo assignRole( @PathParam( "roleId" ) String roleId, @PathParam( "userId" ) String userId )
+ throws RedbackServiceException;
+
+ /**
+ * Deletes the assignment of a role to a user.
+ *
+ * @param roleId the role id
+ * @param userId the user id
* @throws RedbackServiceException
*/
@Path( "{roleId}/user/{userId}" )
@@ -357,9 +359,40 @@
content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
}
)
- RoleInfo unassignRole( @PathParam( "roleId" ) String roleId, @PathParam( "userId" ) String userId )
+ RoleInfo deleteRoleAssignment( @PathParam( "roleId" ) String roleId, @PathParam( "userId" ) String userId )
throws RedbackServiceException;
+ @Path("{roleId}/user")
+ @GET
+ @Produces({APPLICATION_JSON})
+ @RedbackAuthorization(permissions = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION)
+ @Operation( summary = "Returns the users assigned to the given role",
+ parameters = {
+ @Parameter(name = "q", description = "Search term"),
+ @Parameter(name = "offset", description = "The offset of the first element returned"),
+ @Parameter(name = "limit", description = "Maximum number of items to return in the response"),
+ @Parameter(name = "orderBy", description = "List of attribute used for sorting (user_id, fullName, email, created"),
+ @Parameter(name = "order", description = "The sort order. Either ascending (asc) or descending (desc)")
+ },
+ security = {
+ @SecurityRequirement( name = RedbackRoleConstants.USER_MANAGEMENT_RBAC_ADMIN_OPERATION )
+ },
+ responses = {
+ @ApiResponse( responseCode = "200",
+ description = "If the users could be retrieved"
+ ),
+ @ApiResponse( responseCode = "404", description = "Role instance does not exist",
+ content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) ),
+ @ApiResponse( responseCode = "403", description = "The authenticated user has not the permission for role assignment.",
+ content = @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = RedbackRestError.class )) )
+ }
+ )
+ PagedResult<UserInfo> getRoleUsers(@PathParam( "roleId" ) String roleId,
+ @QueryParam("q") @DefaultValue( "" ) String searchTerm,
+ @QueryParam( "offset" ) @DefaultValue( "0" ) Integer offset,
+ @QueryParam( "limit" ) @DefaultValue( value = DEFAULT_PAGE_LIMIT ) Integer limit,
+ @QueryParam( "orderBy") @DefaultValue( "id" ) List<String> orderBy,
+ @QueryParam("order") @DefaultValue( "asc" ) String order) throws RedbackServiceException;
/**
* Updates a role. Attributes that are empty or null will be ignored.
diff --git a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/interceptors/RequestValidationInterceptor.java b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/interceptors/RequestValidationInterceptor.java
index 7553cf0..fb3e72e 100644
--- a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/interceptors/RequestValidationInterceptor.java
+++ b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/interceptors/RequestValidationInterceptor.java
@@ -127,7 +127,7 @@
"origin, content-type, accept, authorization");
responseContext.getHeaders().add(
"Access-Control-Allow-Methods",
- "GET, POST, PUT, DELETE, OPTIONS, HEAD");
+ "GET, POST, PUT, DELETE, OPTIONS, HEAD, PATCH");
}
private class HeaderValidationInfo
diff --git a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/BaseRedbackService.java b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/BaseRedbackService.java
index 4dc9ab3..48de1bb 100644
--- a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/BaseRedbackService.java
+++ b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/BaseRedbackService.java
@@ -24,18 +24,26 @@
import org.apache.archiva.redback.rest.api.MessageKeys;
import org.apache.archiva.redback.rest.api.model.ErrorMessage;
import org.apache.archiva.redback.rest.api.model.v2.BaseUserInfo;
+import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
import org.apache.archiva.redback.rest.api.model.v2.RoleInfo;
+import org.apache.archiva.redback.rest.api.model.v2.UserInfo;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import org.apache.archiva.redback.users.User;
import org.apache.archiva.redback.users.UserManager;
import org.apache.archiva.redback.users.UserManagerException;
+import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Named;
import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
+import java.util.function.BiPredicate;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -44,8 +52,36 @@
*/
public class BaseRedbackService
{
+ protected static final String[] DEFAULT_SEARCH_FIELDS = {"user_id", "full_name", "email"};
+ protected static final Map<String, BiPredicate<String, User>> USER_FILTER_MAP = new HashMap<>( );
+ protected static final Map<String, Comparator<User>> USER_ORDER_MAP = new HashMap<>( );
+ protected static final QueryHelper<User> USER_QUERY_HELPER;
private static final Logger log = LoggerFactory.getLogger( BaseRedbackService.class );
+
+ static
+ {
+ // The simple Comparator.comparing(attribute) is not null safe
+ // As there are attributes that may have a null value, we have to use a comparator with nullsLast(naturalOrder)
+ // and the wrapping Comparator.nullsLast(Comparator.comparing(attribute)) does not work, because the attribute is not checked by the nullsLast-Comparator
+ USER_ORDER_MAP.put( "id", Comparator.comparing( org.apache.archiva.redback.users.User::getId, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
+ USER_ORDER_MAP.put( "user_id", Comparator.comparing( org.apache.archiva.redback.users.User::getUsername, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
+ USER_ORDER_MAP.put( "full_name", Comparator.comparing( org.apache.archiva.redback.users.User::getFullName, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
+ USER_ORDER_MAP.put( "email", Comparator.comparing( org.apache.archiva.redback.users.User::getEmail, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
+ USER_ORDER_MAP.put( "created", Comparator.comparing( org.apache.archiva.redback.users.User::getAccountCreationDate, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
+ USER_ORDER_MAP.put( "last_login", Comparator.comparing( org.apache.archiva.redback.users.User::getLastLoginDate, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
+ USER_ORDER_MAP.put( "validated", Comparator.comparing( org.apache.archiva.redback.users.User::isValidated, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
+ USER_ORDER_MAP.put( "locked", Comparator.comparing( org.apache.archiva.redback.users.User::isLocked, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
+ USER_ORDER_MAP.put( "password_change_required", Comparator.comparing( org.apache.archiva.redback.users.User::isPasswordChangeRequired, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
+ USER_ORDER_MAP.put( "last_password_change", Comparator.comparing( org.apache.archiva.redback.users.User::getLastPasswordChange, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
+
+ USER_FILTER_MAP.put( "user_id", ( String q, org.apache.archiva.redback.users.User u ) -> StringUtils.containsIgnoreCase( u.getUsername( ), q ) );
+ USER_FILTER_MAP.put( "full_name", ( String q, org.apache.archiva.redback.users.User u ) -> StringUtils.containsIgnoreCase( u.getFullName( ), q ) );
+ USER_FILTER_MAP.put( "email", ( String q, org.apache.archiva.redback.users.User u ) -> StringUtils.containsIgnoreCase( u.getEmail( ), q ) );
+
+ USER_QUERY_HELPER = new QueryHelper<>( USER_FILTER_MAP, USER_ORDER_MAP, DEFAULT_SEARCH_FIELDS );
+ }
+
protected RBACManager rbacManager;
protected UserManager userManager;
@@ -62,7 +98,6 @@
RoleInfo role = RoleInfo.of( rbacRole );
role.setParentRoleIds( getParentRoles( rbacRole ) );
role.setChildRoleIds( getChildRoles( rbacRole ) );
- role.setAssignedUsers( getAssignedUsersRecursive( rbacRole ) );
return role;
}
catch ( RbacManagerException e )
@@ -72,6 +107,10 @@
}
}
+ protected boolean isAscending(String order) {
+ return !"desc".equals( order );
+ }
+
protected List<String> getParentRoles( org.apache.archiva.redback.rbac.Role rbacRole ) throws RbacManagerException
{
return new ArrayList<>( rbacManager.getParentRoleIds( rbacRole ).keySet( ));
@@ -96,6 +135,33 @@
}
}
+ protected List<User> getAssignedRedbackUsersRecursive( org.apache.archiva.redback.rbac.Role rbacRole ) throws RbacManagerException
+ {
+ try
+ {
+ return rbacManager.getUserAssignmentsForRoles( recurseRoles( rbacRole ).map( role -> role.getId( ) ).collect( Collectors.toList( ) ) )
+ .stream( ).map( assignment -> getRedbackUser( assignment.getPrincipal( ) ) ).collect( Collectors.toList( ) );
+ }
+ catch ( RuntimeException e )
+ {
+ log.error( "Could not recurse roles for assignments {}", e.getMessage( ) );
+ throw new RbacManagerException( e.getCause( ) );
+ }
+ }
+
+ protected User getRedbackUser(String userId) throws RuntimeException {
+ try
+ {
+ return userManager.findUser( userId, true );
+ }
+ catch ( UserManagerException e )
+ {
+ throw new RuntimeException( e );
+ }
+ }
+
+
+
private Stream<Role> recurseRoles( Role startRole )
{
return Stream.concat( Stream.of( startRole ), getParentRoleStream( startRole ).flatMap( this::recurseRoles ) ).distinct( );
@@ -133,7 +199,6 @@
RoleInfo role = RoleInfo.of( rbacRole );
role.setParentRoleIds( getParentRoles( rbacRole ) );
role.setChildRoleIds( getChildRoles( rbacRole ) );
- role.setAssignedUsers( getAssignedUsersRecursive( rbacRole ) );
return Optional.of( role );
}
catch ( RbacManagerException e )
@@ -142,4 +207,25 @@
return Optional.empty( );
}
}
+
+ protected UserInfo getRestUser( User user )
+ {
+ if ( user == null )
+ {
+ return null;
+ }
+ return new UserInfo( user );
+ }
+
+ protected PagedResult<UserInfo> getUserInfoPagedResult( List<? extends User> rawUsers, String q, Integer offset, Integer limit, List<String> orderBy, boolean ascending)
+ {
+ Predicate<User> filter = USER_QUERY_HELPER.getQueryFilter( q );
+ long size = rawUsers.stream( ).filter( filter ).count( );
+ List<UserInfo> users = rawUsers.stream( )
+ .filter( filter )
+ .sorted( USER_QUERY_HELPER.getComparator( orderBy, ascending ) ).skip( offset ).limit( limit )
+ .map( user -> getRestUser( user ) )
+ .collect( Collectors.toList( ) );
+ return new PagedResult<>( (int) size, offset, limit, users );
+ }
}
diff --git a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultRoleService.java b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultRoleService.java
index 43adc13..ea0c34c 100644
--- a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultRoleService.java
+++ b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultRoleService.java
@@ -27,6 +27,7 @@
import org.apache.archiva.redback.rest.api.model.v2.Role;
import org.apache.archiva.redback.rest.api.model.v2.RoleInfo;
import org.apache.archiva.redback.rest.api.model.v2.RoleTemplate;
+import org.apache.archiva.redback.rest.api.model.v2.UserInfo;
import org.apache.archiva.redback.rest.api.services.RedbackServiceException;
import org.apache.archiva.redback.rest.api.services.v2.RoleService;
import org.apache.archiva.redback.role.PermanentRoleDeletionInvalid;
@@ -34,9 +35,8 @@
import org.apache.archiva.redback.role.RoleManager;
import org.apache.archiva.redback.role.RoleManagerException;
import org.apache.archiva.redback.role.RoleNotFoundException;
-import org.apache.archiva.redback.role.model.ModelApplication;
-import org.apache.archiva.redback.role.model.ModelTemplate;
import org.apache.archiva.redback.role.util.RoleModelUtils;
+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;
@@ -83,7 +83,7 @@
@Context
private UriInfo uriInfo;
- private static final String[] DEFAULT_SEARCH_FIELDS = {"name", "description"};
+ private static final String[] DEFAULT_SEARCH_FIELDS = {"id", "name", "description"};
private static final Map<String, BiPredicate<String, org.apache.archiva.redback.rbac.Role>> FILTER_MAP = new HashMap<>( );
private static final Map<String, Comparator<org.apache.archiva.redback.rbac.Role>> ORDER_MAP = new HashMap<>( );
private static final QueryHelper<org.apache.archiva.redback.rbac.Role> QUERY_HELPER;
@@ -92,6 +92,7 @@
{
QUERY_HELPER = new QueryHelper<>( FILTER_MAP, ORDER_MAP, DEFAULT_SEARCH_FIELDS );
+ QUERY_HELPER.addStringFilter( "id", org.apache.archiva.redback.rbac.Role::getId );
QUERY_HELPER.addStringFilter( "name", org.apache.archiva.redback.rbac.Role::getName );
QUERY_HELPER.addStringFilter( "description", org.apache.archiva.redback.rbac.Role::getDescription );
QUERY_HELPER.addBooleanFilter( "assignable", org.apache.archiva.redback.rbac.Role::isAssignable );
@@ -103,6 +104,7 @@
QUERY_HELPER.addNullsafeFieldComparator( "id", org.apache.archiva.redback.rbac.Role::getId );
QUERY_HELPER.addNullsafeFieldComparator( "resource", org.apache.archiva.redback.rbac.Role::getResource );
QUERY_HELPER.addNullsafeFieldComparator( "assignable", org.apache.archiva.redback.rbac.Role::isAssignable );
+ QUERY_HELPER.addNullsafeFieldComparator( "description", org.apache.archiva.redback.rbac.Role::getDescription );
QUERY_HELPER.addNullsafeFieldComparator( "template_instance", org.apache.archiva.redback.rbac.Role::isTemplateInstance );
}
@@ -121,7 +123,7 @@
@Override
public PagedResult<RoleInfo> getAllRoles( String searchTerm, Integer offset, Integer limit, List<String> orderBy, String order ) throws RedbackServiceException
{
- boolean ascending = !"desc".equals( order );
+ boolean ascending = isAscending( order );
try
{
// UserQuery does not work here, because the configurable user manager does only return the query for
@@ -389,7 +391,7 @@
}
@Override
- public RoleInfo unassignRole( String roleId, String userId )
+ public RoleInfo deleteRoleAssignment( String roleId, String userId )
throws RedbackServiceException
{
try
@@ -415,8 +417,28 @@
}
catch ( RbacObjectNotFoundException e )
{
+ throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLE_NOT_FOUND, e.getMessage( ) ), 404 );
+ }
+ catch ( RbacManagerException e )
+ {
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_RBACMANAGER_FAIL, e.getMessage( ) ) );
}
+ }
+
+ @Override
+ public PagedResult<UserInfo> getRoleUsers( String roleId, String searchTerm, Integer offset, Integer limit, List<String> orderBy, String order ) throws RedbackServiceException
+ {
+ boolean ascending = isAscending( order );
+ try
+ {
+ org.apache.archiva.redback.rbac.Role rbacRole = rbacManager.getRoleById( roleId );
+ List<User> rawUsers = getAssignedRedbackUsersRecursive( rbacRole );
+ return getUserInfoPagedResult( rawUsers, searchTerm, offset, limit, orderBy, ascending );
+ }
+ catch ( RbacObjectNotFoundException e )
+ {
+ throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_ROLE_NOT_FOUND, e.getMessage( ) ), 404 );
+ }
catch ( RbacManagerException e )
{
throw new RedbackServiceException( ErrorMessage.of( MessageKeys.ERR_RBACMANAGER_FAIL, e.getMessage( ) ) );
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 f32d595..b89a550 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
@@ -102,7 +102,6 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -118,33 +117,6 @@
private static final String VALID_USERNAME_CHARS = "[a-zA-Z_0-9\\-.@]*";
private static final String[] INVALID_CREATE_USER_NAMES = {"admin", "guest", "me"};
- private static final String[] DEFAULT_SEARCH_FIELDS = {"user_id", "full_name", "email"};
- private static final Map<String, BiPredicate<String, org.apache.archiva.redback.users.User>> FILTER_MAP = new HashMap<>( );
- private static final Map<String, Comparator<org.apache.archiva.redback.users.User>> ORDER_MAP = new HashMap<>( );
- private static final QueryHelper<org.apache.archiva.redback.users.User> QUERY_HELPER;
-
- static
- {
- // The simple Comparator.comparing(attribute) is not null safe
- // As there are attributes that may have a null value, we have to use a comparator with nullsLast(naturalOrder)
- // and the wrapping Comparator.nullsLast(Comparator.comparing(attribute)) does not work, because the attribute is not checked by the nullsLast-Comparator
- ORDER_MAP.put( "id", Comparator.comparing( org.apache.archiva.redback.users.User::getId, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
- ORDER_MAP.put( "user_id", Comparator.comparing( org.apache.archiva.redback.users.User::getUsername, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
- ORDER_MAP.put( "full_name", Comparator.comparing( org.apache.archiva.redback.users.User::getFullName, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
- ORDER_MAP.put( "email", Comparator.comparing( org.apache.archiva.redback.users.User::getEmail, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
- ORDER_MAP.put( "created", Comparator.comparing( org.apache.archiva.redback.users.User::getAccountCreationDate, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
- ORDER_MAP.put( "last_login", Comparator.comparing( org.apache.archiva.redback.users.User::getLastLoginDate, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
- ORDER_MAP.put( "validated", Comparator.comparing( org.apache.archiva.redback.users.User::isValidated, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
- ORDER_MAP.put( "locked", Comparator.comparing( org.apache.archiva.redback.users.User::isLocked, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
- ORDER_MAP.put( "password_change_required", Comparator.comparing( org.apache.archiva.redback.users.User::isPasswordChangeRequired, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
- ORDER_MAP.put( "last_password_change", Comparator.comparing( org.apache.archiva.redback.users.User::getLastPasswordChange, Comparator.nullsLast( Comparator.naturalOrder( ) ) ) );
-
- FILTER_MAP.put( "user_id", ( String q, org.apache.archiva.redback.users.User u ) -> StringUtils.containsIgnoreCase( u.getUsername( ), q ) );
- FILTER_MAP.put( "full_name", ( String q, org.apache.archiva.redback.users.User u ) -> StringUtils.containsIgnoreCase( u.getFullName( ), q ) );
- FILTER_MAP.put( "email", ( String q, org.apache.archiva.redback.users.User u ) -> StringUtils.containsIgnoreCase( u.getEmail( ), q ) );
-
- QUERY_HELPER = new QueryHelper<>( FILTER_MAP, ORDER_MAP, DEFAULT_SEARCH_FIELDS );
- }
private SecuritySystem securitySystem;
@@ -395,20 +367,13 @@
Integer limit, List<String> orderBy, String order )
throws RedbackServiceException
{
- boolean ascending = !"desc".equals( order );
+ boolean ascending = isAscending( order );
try
{
// UserQuery does not work here, because the configurable user manager does only return the query for
// the first user manager in the list. So we have to fetch the whole user list
List<? extends org.apache.archiva.redback.users.User> rawUsers = userManager.getUsers( );
- Predicate<org.apache.archiva.redback.users.User> filter = QUERY_HELPER.getQueryFilter( q );
- long size = rawUsers.stream( ).filter( filter ).count( );
- List<UserInfo> users = rawUsers.stream( )
- .filter( filter )
- .sorted( QUERY_HELPER.getComparator( orderBy, ascending ) ).skip( offset ).limit( limit )
- .map( user -> getRestUser( user ) )
- .collect( Collectors.toList( ) );
- return new PagedResult<>( (int) size, offset, limit, users );
+ return getUserInfoPagedResult( rawUsers, q, offset, limit, orderBy, ascending );
}
catch ( UserManagerException e )
{
@@ -416,6 +381,7 @@
}
}
+
@Override
public UserInfo updateMe( SelfUserData user )
throws RedbackServiceException
@@ -573,15 +539,6 @@
return new PingResult( true );
}
- private UserInfo getRestUser( org.apache.archiva.redback.users.User user )
- {
- if ( user == null )
- {
- return null;
- }
- return new UserInfo( user );
- }
-
@Override
public UserInfo createAdminUser( User adminUser )
throws RedbackServiceException
diff --git a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeRoleServiceTest.java b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeRoleServiceTest.java
index 936a160..125b8f0 100644
--- a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeRoleServiceTest.java
+++ b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeRoleServiceTest.java
@@ -19,8 +19,14 @@
*/
import io.restassured.response.Response;
+import io.restassured.response.ResponseBodyExtractionOptions;
+import org.apache.archiva.redback.rest.api.model.User;
+import org.apache.archiva.redback.rest.api.model.v2.BaseUserInfo;
+import org.apache.archiva.redback.rest.api.model.v2.PagedResult;
+import org.apache.archiva.redback.rest.api.model.v2.Permission;
import org.apache.archiva.redback.rest.api.model.v2.RoleInfo;
import org.apache.archiva.redback.rest.api.model.v2.RoleTemplate;
+import org.apache.archiva.redback.rest.api.model.v2.UserInfo;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
@@ -38,8 +44,8 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
-import static io.restassured.RestAssured.get;
import static io.restassured.RestAssured.given;
import static io.restassured.http.ContentType.JSON;
import static org.apache.archiva.redback.rest.api.Constants.DEFAULT_PAGE_LIMIT;
@@ -142,26 +148,26 @@
void deleteTemplatedRole( )
{
String token = getAdminToken( );
- given( ).spec( getRequestSpec( token ) ).contentType( JSON )
- .when( )
- .put( "templates/archiva-repository-manager/repository05" )
- .then( ).statusCode( 201 ).extract( ).response( );
- given( ).spec( getRequestSpec( token ) ).contentType( JSON )
- .when( )
- .delete( "templates/archiva-repository-manager/repository01" )
- .then( ).statusCode( 404 );
- given( ).spec( getRequestSpec( token ) ).contentType( JSON )
- .when( )
- .delete( "templates/archiva-repository-manager/repository05" )
- .then( ).statusCode( 200 );
- given( ).spec( getRequestSpec( token ) ).contentType( JSON )
- .when( )
- .delete( "templates/archiva-repository-manager/repository05" )
- .then( ).statusCode( 404 );
- given( ).spec( getRequestSpec( token ) ).contentType( JSON )
- .when( )
- .delete( "templates/archiva-repository-observer/repository05" )
- .then( ).statusCode( 200 );
+ given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .put( "templates/archiva-repository-manager/repository05" )
+ .then( ).statusCode( 201 ).extract( ).response( );
+ given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .delete( "templates/archiva-repository-manager/repository01" )
+ .then( ).statusCode( 404 );
+ given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .delete( "templates/archiva-repository-manager/repository05" )
+ .then( ).statusCode( 200 );
+ given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .delete( "templates/archiva-repository-manager/repository05" )
+ .then( ).statusCode( 404 );
+ given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .delete( "templates/archiva-repository-observer/repository05" )
+ .then( ).statusCode( 200 );
}
@@ -343,12 +349,20 @@
{
String token = getAdminToken( );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
- .when( ).get( "archiva-system-administrator" ).then( ).statusCode( 200 ).extract( ).response( );
+ .when( ).get( "archiva-system-administrator" ).prettyPeek( ).then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );
RoleInfo roleInfo = response.getBody( ).jsonPath( ).getObject( "", RoleInfo.class );
assertNotNull( roleInfo );
assertEquals( "archiva-system-administrator", roleInfo.getId( ) );
assertEquals( "Archiva System Administrator", roleInfo.getName( ) );
+ List<Permission> perms = roleInfo.getPermissions( );
+ assertNotNull( perms );
+ assertTrue( perms.size( ) > 0 );
+ assertTrue( perms.stream( ).filter( perm -> "archiva-manage-configuration".equals( perm.getName( ) ) ).findAny( ).isPresent( ) );
+ List<String> childs = roleInfo.getChildRoleIds( );
+ assertNotNull( childs );
+ assertTrue( childs.size( ) > 0 );
+ assertTrue( childs.stream( ).filter( id -> "archiva-global-repository-manager".equals( id ) ).findAny( ).isPresent( ) );
}
@Test
@@ -463,6 +477,47 @@
}
+ @Test
+ void getAssignedUsers( )
+ {
+ String token = getAdminToken( );
+ Map<String, Object> jsonAsMap = new HashMap<>( );
+ jsonAsMap.put( "user_id", "aragorn" );
+ jsonAsMap.put( "email", "aragorn@lordoftherings.org" );
+ jsonAsMap.put( "full_name", "Aragorn King of Gondor " );
+ jsonAsMap.put( "password", "pAssw0rD" );
+
+ try
+ {
+ given( ).spec( getRequestSpec( token, getUserServicePath( ) ) ).contentType( JSON )
+ .body( jsonAsMap )
+ .when( )
+ .post( )
+ .then( ).statusCode( 201 );
+ given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .put( "system-administrator/user/aragorn" )
+ .then( ).statusCode( 200 );
+ Response result = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .get( "system-administrator/user" )
+ .prettyPeek()
+ .then( ).statusCode( 200 ).extract( ).response( );
+ assertNotNull(result);
+ PagedResult<UserInfo> userResult = result.getBody( ).jsonPath( ).getObject( "", PagedResult.class );
+ assertNotNull( userResult );
+ assertEquals( 2, userResult.getPagination( ).getTotalCount( ) );
+ List<UserInfo> users = result.getBody( ).jsonPath( ).getList( "data", UserInfo.class );
+ assertArrayEquals( new String[] {"admin","aragorn"}, users.stream( ).map( BaseUserInfo::getUserId ).sorted().toArray(String[]::new) );
+ }
+ finally
+ {
+ given( ).spec( getRequestSpec( token, getUserServicePath( ) ) ).contentType( JSON )
+ .when( )
+ .delete( "aragorn" ).then( ).statusCode( 200 );
+ }
+
+ }
@Test
void assignRole( )
@@ -503,7 +558,7 @@
{
given( ).spec( getRequestSpec( token, getUserServicePath( ) ) ).contentType( JSON )
.when( )
- .delete( "aragorn" ).then().statusCode( 200 );
+ .delete( "aragorn" ).then( ).statusCode( 200 );
}
}
@@ -546,7 +601,7 @@
{
given( ).spec( getRequestSpec( token, getUserServicePath( ) ) ).contentType( JSON )
.when( )
- .delete( "aragorn" ).then().statusCode( 200 );
+ .delete( "aragorn" ).then( ).statusCode( 200 );
}
}
@@ -605,13 +660,13 @@
{
given( ).spec( getRequestSpec( token, getUserServicePath( ) ) ).contentType( JSON )
.when( )
- .delete( "aragorn" ).then().statusCode( 200 );
+ .delete( "aragorn" ).then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
- .delete( "templates/archiva-repository-manager/repository11" ).then().statusCode( 200 );
+ .delete( "templates/archiva-repository-manager/repository11" ).then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
- .delete( "templates/archiva-repository-observer/repository11" ).then().statusCode( 200 );
+ .delete( "templates/archiva-repository-observer/repository11" ).then( ).statusCode( 200 );
}
}
@@ -659,7 +714,7 @@
{
given( ).spec( getRequestSpec( token, getUserServicePath( ) ) ).contentType( JSON )
.when( )
- .delete( "aragorn" ).then().statusCode( 200 );
+ .delete( "aragorn" ).then( ).statusCode( 200 );
}
}
@@ -709,13 +764,13 @@
{
given( ).spec( getRequestSpec( token, getUserServicePath( ) ) ).contentType( JSON )
.when( )
- .delete( "aragorn" ).then().statusCode( 200 );
+ .delete( "aragorn" ).then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
- .delete( "templates/archiva-repository-manager/repository12" ).then().statusCode( 200 );
+ .delete( "templates/archiva-repository-manager/repository12" ).then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
- .delete( "templates/archiva-repository-observer/repository12" ).then().statusCode( 200 );
+ .delete( "templates/archiva-repository-observer/repository12" ).then( ).statusCode( 200 );
}
}
@@ -748,7 +803,13 @@
assertEquals( "This description was updated.", updatedRole.getDescription( ) );
assertEquals( true, updatedRole.isAssignable( ) );
assertEquals( false, updatedRole.isPermanent( ) );
- assertArrayEquals( roleInfo.getAssignedUsers( ).toArray( ), updatedRole.getAssignedUsers( ).toArray( ) );
+ response = given().spec(getRequestSpec(token)).contentType( JSON )
+ .when()
+ .get("archiva-repository-manager.repository13/user")
+ .then()
+ .extract( ).response( );
+ List<UserInfo> userList = response.getBody( ).jsonPath( ).getList( "data", UserInfo.class );
+ assertEquals( 1, userList.size( ) );
}
finally
{
@@ -812,8 +873,15 @@
assertEquals( "New description", updatedRole.getDescription( ) );
assertEquals( false, updatedRole.isAssignable( ) );
assertEquals( true, updatedRole.isPermanent( ) );
- assertEquals( 2, updatedRole.getAssignedUsers( ).size() );
- assertTrue( updatedRole.getAssignedUsers( ).stream( ).filter( user -> "aragorn".equals( user.getUserId( ) ) ).findAny().isPresent() );
+
+ response = given().spec(getRequestSpec(token)).contentType( JSON )
+ .when()
+ .get("archiva-repository-manager.repository14/user")
+ .then()
+ .extract( ).response( );
+ List<UserInfo> userList = response.getBody( ).jsonPath( ).getList( "data", UserInfo.class );
+ assertEquals( 2, userList.size( ) );
+ assertTrue( userList.stream( ).filter( user -> "aragorn".equals( user.getUserId( ) ) ).findAny( ).isPresent( ) );
}
finally
{
@@ -829,7 +897,7 @@
given( ).spec( getRequestSpec( token, getUserServicePath( ) ) ).contentType( JSON )
.when( )
- .delete( "aragorn" ).then().statusCode( 200 );
+ .delete( "aragorn" ).then( ).statusCode( 200 );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
@@ -937,20 +1005,21 @@
void updateRoleNotExist( )
{
String token = getAdminToken( );
- Map<String, Object> jsonAsMap = new HashMap<>( );
- jsonAsMap.put( "id", "abcdefg" );
- jsonAsMap.put( "name", "abcdefg" );
- jsonAsMap.put( "description", "This description was updated." );
- given( ).spec( getRequestSpec( token ) ).contentType( JSON )
- .when( )
- .body( jsonAsMap )
- .patch( "abcdefg" )
- .then( ).statusCode( 404 );
+ Map<String, Object> jsonAsMap = new HashMap<>( );
+ jsonAsMap.put( "id", "abcdefg" );
+ jsonAsMap.put( "name", "abcdefg" );
+ jsonAsMap.put( "description", "This description was updated." );
+ given( ).spec( getRequestSpec( token ) ).contentType( JSON )
+ .when( )
+ .body( jsonAsMap )
+ .patch( "abcdefg" )
+ .then( ).statusCode( 404 );
}
@Test
- void getTemplates() {
+ void getTemplates( )
+ {
String token = getAdminToken( );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
@@ -959,8 +1028,8 @@
assertNotNull( response );
List<RoleTemplate> templates = response.getBody( ).jsonPath( ).getList( "", RoleTemplate.class );
assertEquals( 2, templates.size( ) );
- assertTrue( templates.stream( ).filter( tmpl -> "archiva-repository-manager".equals( tmpl.getId( ) ) ).findAny().isPresent() );
- assertTrue( templates.stream( ).filter( tmpl -> "archiva-repository-observer".equals( tmpl.getId( ) ) ).findAny().isPresent() );
+ assertTrue( templates.stream( ).filter( tmpl -> "archiva-repository-manager".equals( tmpl.getId( ) ) ).findAny( ).isPresent( ) );
+ assertTrue( templates.stream( ).filter( tmpl -> "archiva-repository-observer".equals( tmpl.getId( ) ) ).findAny( ).isPresent( ) );
}
}