diff --git a/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/ObjectNotFoundException.java b/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/ObjectNotFoundException.java new file mode 100644 index 00000000..c3932c22 --- /dev/null +++ b/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/ObjectNotFoundException.java @@ -0,0 +1,35 @@ +package org.apache.archiva.redback.common.ldap; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * @author Martin Stockhammer + */ +public class ObjectNotFoundException extends MappingException +{ + public ObjectNotFoundException( String message, Throwable cause ) + { + super( message, cause ); + } + + public ObjectNotFoundException( String message ) + { + super( message ); + } +} diff --git a/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/DefaultLdapRoleMapper.java b/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/DefaultLdapRoleMapper.java index afe3d5ee..64f5fce8 100644 --- a/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/DefaultLdapRoleMapper.java +++ b/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/DefaultLdapRoleMapper.java @@ -19,6 +19,7 @@ package org.apache.archiva.redback.common.ldap.role; */ import org.apache.archiva.redback.common.ldap.MappingException; +import org.apache.archiva.redback.common.ldap.ObjectNotFoundException; import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory; import org.apache.archiva.redback.common.ldap.connection.LdapException; import org.apache.archiva.redback.common.ldap.user.LdapUser; @@ -275,7 +276,48 @@ public class DefaultLdapRoleMapper } } - LdapGroup getGroupFromResult(SearchResult searchResult) throws NamingException + @Override + public LdapGroup getGroupForName( DirContext context, String groupName ) throws MappingException + { + NamingEnumeration namingEnumeration = null; + try + { + + SearchControls searchControls = new SearchControls( ); + + searchControls.setDerefLinkFlag( true ); + searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE ); + searchControls.setReturningAttributes( new String[]{this.getLdapDnAttribute( ), "objectClass", groupNameAttribute, + ldapGroupMemberAttribute} ); + + StringBuilder fiBuilder = new StringBuilder("(&(objectClass=" ).append( getLdapGroupClass( ) ).append(")"); + + + if ( !StringUtils.isEmpty( this.groupFilter ) ) + { + fiBuilder.append("(").append(this.groupFilter).append(")"); + } + fiBuilder.append("(").append(this.groupNameAttribute) + .append("=").append(groupName).append("))"); + namingEnumeration = context.search( getGroupsDn( ), fiBuilder.toString(), searchControls ); + if (namingEnumeration.hasMore()) { + SearchResult result = namingEnumeration.next( ); + return getGroupFromResult( result ); + } else { + throw new ObjectNotFoundException( "Group not found " + groupName ); + } + } + catch ( NamingException e ) + { + log.error( "Naming error while searching for group {}: {}", groupName, e.getMessage( ) ); + throw new MappingException( "Group search failed " + e.getMessage( ), e ); + } finally + { + closeNamingEnumeration( namingEnumeration ); + } + } + + private LdapGroup getGroupFromResult(SearchResult searchResult) throws NamingException { LdapGroup group = new LdapGroup( searchResult.getNameInNamespace() ); Attribute attValue = searchResult.getAttributes( ).get( groupNameAttribute ); diff --git a/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/LdapRoleMapper.java b/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/LdapRoleMapper.java index 016d5f0f..1ee2cfe5 100644 --- a/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/LdapRoleMapper.java +++ b/redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/LdapRoleMapper.java @@ -44,13 +44,16 @@ public interface LdapRoleMapper throws MappingException; /** - * read all groups from ldap + * Read all groups from LDAP and return the list of group objects. * - * @return all LDAP groups + * @return all LDAP groups found in the LDAP directory */ List getAllGroupObjects( DirContext context ) throws MappingException; + LdapGroup getGroupForName( DirContext context, String groupName ) + throws MappingException; + /** * read all ldap groups then map to corresponding role (if no mapping found group is ignored) * diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/ActionStatus.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/ActionStatus.java index 9ed23bce..547187b8 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/ActionStatus.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/ActionStatus.java @@ -18,12 +18,15 @@ package org.apache.archiva.redback.rest.api.model; * under the License. */ +import io.swagger.v3.oas.annotations.media.Schema; + import javax.xml.bind.annotation.XmlRootElement; /** * @author Martin Stockhammer */ -@XmlRootElement(name = "actionStatus") +@XmlRootElement( name = "actionStatus" ) +@Schema( name = "ActionStatus", description = "Status result of a updating action, like post, put, delete" ) public class ActionStatus { private boolean success = false; @@ -31,23 +34,28 @@ public class ActionStatus public static final ActionStatus SUCCESS = new ActionStatus( true ); public static final ActionStatus FAIL = new ActionStatus( false ); - public static ActionStatus FROM(boolean status) { + + public static ActionStatus FROM( boolean status ) + { return status ? SUCCESS : FAIL; } - public ActionStatus() { + public ActionStatus( ) + { } - public ActionStatus( boolean success) { + public ActionStatus( boolean success ) + { this.success = success; } - public ActionStatus(boolean success, int modifiedNumber) { + public ActionStatus( boolean success, int modifiedNumber ) + { this.success = success; this.modifiedNumber = modifiedNumber; } - + public boolean isSuccess( ) { return success; diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/Group.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/Group.java index 2b07e320..05d2e082 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/Group.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/Group.java @@ -26,7 +26,9 @@ import java.util.ArrayList; import java.util.List; /** + * REST API Version 2 group element * @author Martin Stockhammer + * @since 3.0 */ @XmlRootElement(name="group") @Schema(name="Group", description = "Group object") diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/GroupMapping.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/GroupMapping.java index c59d2e9c..b7d48c95 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/GroupMapping.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/GroupMapping.java @@ -18,6 +18,8 @@ package org.apache.archiva.redback.rest.api.model; * under the License. */ +import io.swagger.v3.oas.annotations.media.Schema; + import javax.xml.bind.annotation.XmlRootElement; import java.io.Serializable; import java.util.Collection; @@ -28,6 +30,7 @@ import java.util.List; * @since 2.1 */ @XmlRootElement(name = "groupMapping") +@Schema(name="GroupMapping", description = "List of Group to Role mappings") public class GroupMapping implements Serializable { @@ -46,6 +49,7 @@ public class GroupMapping this.roleNames = roleNames; } + @Schema(description = "The group name that is mapped") public String getGroup() { return group; @@ -56,6 +60,7 @@ public class GroupMapping this.group = group; } + @Schema(description = "The list of roles that are mapped to this group") public Collection getRoleNames() { return roleNames; diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/GroupMapping.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/GroupMapping.java new file mode 100644 index 00000000..d13e2504 --- /dev/null +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/model/v2/GroupMapping.java @@ -0,0 +1,93 @@ +package org.apache.archiva.redback.rest.api.model.v2; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import io.swagger.v3.oas.annotations.media.Schema; + +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Martin Stockhammer + */ +@XmlRootElement(name="groupMapping") +@Schema(name="GroupMap", description = "Mapping of a group to roles") +public class GroupMapping implements Serializable +{ + private static final long serialVersionUID = 8327221676510149313L; + + String groupName; + String uniqueGroupName; + List roles; + + public GroupMapping( ) + { + } + + public GroupMapping( String groupName, String uniqueGroupName, List roles ) + { + this.groupName = groupName; + this.uniqueGroupName = uniqueGroupName; + this.roles = roles; + } + + @Schema(description = "The name of the mapped group") + public String getGroupName( ) + { + return groupName; + } + + public void setGroupName( String groupName ) + { + this.groupName = groupName; + } + + @Schema(description = "The unique name of the mapped group. Dependent on the used repository backend.") + public String getUniqueGroupName( ) + { + return uniqueGroupName; + } + + public void setUniqueGroupName( String uniqueGroupName ) + { + this.uniqueGroupName = uniqueGroupName; + } + + @Schema(description = "The list of role names mapped to this group") + public List getRoles( ) + { + return roles; + } + + public void setRoles( List roles ) + { + this.roles = roles; + } + + public void addRole(String role) { + if (roles==null) { + this.roles = new ArrayList<>( ); + } + if (!this.roles.contains(role)) { + this.roles.add( role ); + } + } +} diff --git a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/GroupService.java b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/GroupService.java index c626085d..213298c8 100644 --- a/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/GroupService.java +++ b/redback-integrations/redback-rest/redback-rest-api/src/main/java/org/apache/archiva/redback/rest/api/services/v2/GroupService.java @@ -23,15 +23,14 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import io.swagger.v3.oas.annotations.security.SecurityRequirements; import io.swagger.v3.oas.annotations.security.SecurityScheme; import io.swagger.v3.oas.annotations.tags.Tag; import org.apache.archiva.redback.authorization.RedbackAuthorization; import org.apache.archiva.redback.integration.security.role.RedbackRoleConstants; import org.apache.archiva.redback.rest.api.model.ActionStatus; import org.apache.archiva.redback.rest.api.model.Group; -import org.apache.archiva.redback.rest.api.model.GroupMapping; import org.apache.archiva.redback.rest.api.model.GroupMappingUpdateRequest; +import org.apache.archiva.redback.rest.api.model.v2.GroupMapping; import org.apache.archiva.redback.rest.api.model.PagedResult; import org.apache.archiva.redback.rest.api.services.RedbackServiceException; @@ -60,7 +59,7 @@ import java.util.List; public interface GroupService { - public static final String DEFAULT_PAGE_LIMIT = "1000"; + String DEFAULT_PAGE_LIMIT = "1000"; @Path( "" ) @GET @@ -96,12 +95,12 @@ public interface GroupService @RedbackAuthorization( permissions = RedbackRoleConstants.CONFIGURATION_EDIT_OPERATION ) @Operation( summary = "Adds a group mapping", responses = { - @ApiResponse( responseCode = "201", description = "The status of the add action" ), + @ApiResponse( responseCode = "201", description = "If the group addition was successful" ), @ApiResponse( responseCode = "405", description = "Invalid input" ) } ) ActionStatus addGroupMapping( @Parameter( description = "The data of the group mapping", required = true ) - GroupMapping groupMapping ) + GroupMapping groupMapping ) throws RedbackServiceException; @Path( "mappings/{group}" ) @@ -111,7 +110,7 @@ public interface GroupService @RedbackAuthorization( permissions = RedbackRoleConstants.CONFIGURATION_EDIT_OPERATION ) @Operation( summary = "Deletes a group mapping", responses = { - @ApiResponse( description = "The status of the delete action" ), + @ApiResponse( responseCode = "200", description = "If the status of the delete action was successful" ), @ApiResponse( responseCode = "404", description = "Group mapping not found" ) } ) @@ -126,30 +125,15 @@ public interface GroupService @RedbackAuthorization( permissions = RedbackRoleConstants.CONFIGURATION_EDIT_OPERATION ) @Operation( summary = "Updates a group mapping", responses = { - @ApiResponse( description = "The status of the update action" ), + @ApiResponse( description = "If the update was successful" ), @ApiResponse( responseCode = "404", description = "Group mapping not found" ) } ) ActionStatus updateGroupMapping( @Parameter( description = "The group name", required = true ) @PathParam( "group" ) String groupName, - @Parameter( description = "The updated data of the group mapping", required = true ) - GroupMapping groupMapping ) + @Parameter( description = "The updated role list of the group mapping", required = true ) + List roles ) throws RedbackServiceException; - @Path( "mappings" ) - @PUT - @Consumes( {MediaType.APPLICATION_JSON} ) - @Produces( {MediaType.APPLICATION_JSON} ) - @RedbackAuthorization( permissions = RedbackRoleConstants.CONFIGURATION_EDIT_OPERATION ) - @Operation( summary = "Updates multiple group mappings", - responses = { - @ApiResponse( description = "The status of the update action" ), - @ApiResponse( responseCode = "405", description = "Invalid input" ) - } - ) - ActionStatus updateGroupMapping( @Parameter( description = "The list of group mapping updates", required = true ) - GroupMappingUpdateRequest groupMappingUpdateRequest ) - throws RedbackServiceException; - } diff --git a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultGroupService.java b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultGroupService.java index 93ff99b9..4d824a17 100644 --- a/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultGroupService.java +++ b/redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/v2/DefaultGroupService.java @@ -19,6 +19,7 @@ package org.apache.archiva.redback.rest.services.v2; */ import org.apache.archiva.redback.common.ldap.MappingException; +import org.apache.archiva.redback.common.ldap.ObjectNotFoundException; import org.apache.archiva.redback.common.ldap.connection.LdapConnection; import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory; import org.apache.archiva.redback.common.ldap.connection.LdapException; @@ -27,8 +28,8 @@ import org.apache.archiva.redback.common.ldap.role.LdapRoleMapper; 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.Group; -import org.apache.archiva.redback.rest.api.model.GroupMapping; import org.apache.archiva.redback.rest.api.model.GroupMappingUpdateRequest; +import org.apache.archiva.redback.rest.api.model.v2.GroupMapping; import org.apache.archiva.redback.rest.api.model.PagedResult; import org.apache.archiva.redback.rest.api.services.RedbackServiceException; import org.apache.archiva.redback.rest.api.services.v2.GroupService; @@ -113,6 +114,13 @@ public class DefaultGroupService } } + /** + * Tries to retrieve the LDAP group for the mapping to add the unique name. If the group cannot + * be found, it will set "" for the uniqueName + * + * @return the list of mapping + * @throws RedbackServiceException + */ @Override public List getGroupMappings() throws RedbackServiceException @@ -123,8 +131,32 @@ public class DefaultGroupService List ldapGroupMappings = new ArrayList<>( map.size( ) ); for ( Map.Entry> entry : map.entrySet() ) { - GroupMapping ldapGroupMapping = new GroupMapping( entry.getKey( ), new ArrayList<>( entry.getValue( ) ) ); - ldapGroupMappings.add( ldapGroupMapping ); + String groupName = entry.getKey( ); + DirContext context = null; + LdapConnection ldapConnection = null; + try + { + ldapConnection = ldapConnectionFactory.getConnection( ); + context = ldapConnection.getDirContext( ); + + LdapGroup ldapGroup = ldapRoleMapper.getGroupForName( context, groupName ); + GroupMapping ldapGroupMapping = new GroupMapping( ldapGroup.getName(), ldapGroup.getDn(), new ArrayList<>( entry.getValue( ) ) ); + ldapGroupMappings.add( ldapGroupMapping ); + } + catch ( LdapException e ) + { + log.error( "Could not create ldap connection {}", e.getMessage( ) ); + throw new RedbackServiceException( "Error while talking to group registry", 500 ); + } + catch ( ObjectNotFoundException e ) { + GroupMapping ldapGroupMapping = new GroupMapping( groupName, "", new ArrayList<>( entry.getValue( ) ) ); + ldapGroupMappings.add( ldapGroupMapping ); + } + finally + { + closeContext( context ); + closeLdapConnection( ldapConnection ); + } } return ldapGroupMappings; @@ -142,8 +174,8 @@ public class DefaultGroupService { try { - ldapRoleMapperConfiguration.addLdapMapping( ldapGroupMapping.getGroup(), - new ArrayList<>( ldapGroupMapping.getRoleNames() ) ); + ldapRoleMapperConfiguration.addLdapMapping( ldapGroupMapping.getGroupName(), + new ArrayList<>( ldapGroupMapping.getRoles() ) ); response.setStatus( Response.Status.CREATED.getStatusCode() ); } catch ( MappingException e ) @@ -171,7 +203,7 @@ public class DefaultGroupService } @Override - public ActionStatus updateGroupMapping( String groupName, GroupMapping groupMapping ) throws RedbackServiceException + public ActionStatus updateGroupMapping( String groupName, List roles ) throws RedbackServiceException { try { @@ -184,7 +216,7 @@ public class DefaultGroupService try { ldapRoleMapperConfiguration.updateLdapMapping( groupName, - new ArrayList<>( groupMapping.getRoleNames() ) ); + roles ); return ActionStatus.SUCCESS; } catch ( MappingException e ) @@ -194,26 +226,6 @@ public class DefaultGroupService } } - @Override - public ActionStatus updateGroupMapping( GroupMappingUpdateRequest groupMappingUpdateRequest ) - throws RedbackServiceException - { - try - { - for ( GroupMapping ldapGroupMapping : groupMappingUpdateRequest.getGroupMapping() ) - { - ldapRoleMapperConfiguration.updateLdapMapping( ldapGroupMapping.getGroup(), - new ArrayList<>( ldapGroupMapping.getRoleNames() ) ); - } - } - catch ( MappingException e ) - { - log.error( e.getMessage(), e ); - throw new RedbackServiceException( e.getMessage() ); - } - return ActionStatus.SUCCESS; - } - //------------------ // utils //------------------ diff --git a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/GroupServiceTest.java b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/GroupServiceTest.java index b58f6f1d..64f13aba 100644 --- a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/GroupServiceTest.java +++ b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/GroupServiceTest.java @@ -20,7 +20,7 @@ package org.apache.archiva.redback.rest.services.v2; import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; import org.apache.archiva.components.apacheds.ApacheDs; -import org.apache.archiva.redback.rest.api.model.GroupMapping; +import org.apache.archiva.redback.rest.api.model.v2.GroupMapping; import org.apache.archiva.redback.rest.api.services.v2.GroupService; import org.apache.commons.lang3.StringUtils; import org.apache.cxf.jaxrs.client.JAXRSClientFactory; @@ -348,7 +348,7 @@ public class GroupServiceTest assertNotNull( mappings ); assertEquals( 3, mappings.size( ) ); - GroupMapping groupMapping = new GroupMapping( "ldap group", Arrays.asList( "redback role" ) ); + GroupMapping groupMapping = new GroupMapping( "ldap group", "cn=ldap group,ou=archiva,ou=apache,ou=org", Arrays.asList( "redback role" ) ); service.addGroupMapping( groupMapping ); @@ -357,9 +357,9 @@ public class GroupServiceTest assertNotNull( mappings ); assertEquals( 4, mappings.size( ) ); for (GroupMapping mapping : mappings) { - if ( StringUtils.equals( "ldap group", mapping.getGroup( ) ) ) + if ( StringUtils.equals( "ldap group", mapping.getGroupName( ) ) ) { - Collection names = mapping.getRoleNames( ); + Collection names = mapping.getRoles( ); assertNotNull( names ); assertTrue( names.size( ) > 0 ); for (String name : names) { diff --git a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeGroupServiceTest.java b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeGroupServiceTest.java index 9def33d6..6609eaba 100644 --- a/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeGroupServiceTest.java +++ b/redback-integrations/redback-rest/redback-rest-services/src/test/java/org/apache/archiva/redback/rest/services/v2/NativeGroupServiceTest.java @@ -22,15 +22,19 @@ import io.restassured.http.ContentType; import io.restassured.response.Response; import org.apache.archiva.components.apacheds.ApacheDs; 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.services.BaseSetup; import org.apache.archiva.redback.rest.services.LdapInfo; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Tag; 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; @@ -49,9 +53,12 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Hashtable; import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import static io.restassured.RestAssured.given; +import static io.restassured.http.ContentType.JSON; import static org.junit.jupiter.api.Assertions.*; /** @@ -62,6 +69,7 @@ import static org.junit.jupiter.api.Assertions.*; locations = {"classpath:/ldap-spring-test.xml"} ) @TestInstance( TestInstance.Lifecycle.PER_CLASS ) @Tag("rest-native") +@TestMethodOrder( MethodOrderer.Random.class ) public class NativeGroupServiceTest extends AbstractNativeRestServices { protected String peopleSuffix; @@ -307,7 +315,7 @@ public class NativeGroupServiceTest extends AbstractNativeRestServices @Test void getGroups() { String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( ContentType.JSON ).when( ) + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ).when( ) .get( ).then( ).statusCode( 200 ).extract( ).response( ); assertNotNull( response ); List data = response.body( ).jsonPath( ).getList( "data", Group.class ); @@ -326,7 +334,7 @@ public class NativeGroupServiceTest extends AbstractNativeRestServices String token = getAdminToken( ); HashMap params = new HashMap<>( ); params.put( "limit", Long.valueOf( 3 ) ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( ContentType.JSON ) + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) .param( "limit", Long.valueOf( 3 ) ) .when( ) .get( ).then( ).statusCode( 200 ).extract( ).response( ); @@ -345,11 +353,10 @@ public class NativeGroupServiceTest extends AbstractNativeRestServices @Test void getGroupsWithOffset() { String token = getAdminToken( ); - Response response = given( ).spec( getRequestSpec( token ) ).contentType( ContentType.JSON ) + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) .param( "offset", Long.valueOf( 2 ) ) .when( ) .get( ).then( ).statusCode( 200 ).extract( ).response( ); - System.out.println( response.print( ) ); assertNotNull( response ); List data = response.body( ).jsonPath( ).getList( "data", Group.class ); assertNotNull( data ); @@ -363,4 +370,164 @@ public class NativeGroupServiceTest extends AbstractNativeRestServices } + @Test + void getGroupMapping() { + String token = getAdminToken( ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "/mappings" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + assertEquals( 3, response.getBody( ).jsonPath( ).getList( "" ).size() ); + + } + + @Test + void addGroupMapping() { + String token = getAdminToken( ); + try + { + Map jsonAsMap = new HashMap<>( ); + jsonAsMap.put( "groupName", "ldap group" ); + jsonAsMap.put( "roles", Arrays.asList( "role1", "role2" ) ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .body( jsonAsMap ) + .when( ) + .post( "/mappings" ) + .then( ).statusCode( 201 ).extract( ).response( ); + assertNotNull( response ); + assertTrue( response.getBody( ).jsonPath( ).getBoolean( "success" ) ); + } finally { + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .delete( "/mappings/ldap group" ) + .then( ) + .statusCode( 200 ); + } + } + + @Test + void addAndGetGroupMapping() { + String token = getAdminToken( ); + try + { + Map jsonAsMap = new HashMap<>( ); + jsonAsMap.put( "groupName", "ldap group" ); + jsonAsMap.put( "roles", Arrays.asList( "role1", "role2" ) ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .body( jsonAsMap ) + .when( ) + .post( "/mappings" ) + .then( ).statusCode( 201 ).extract( ).response( ); + assertNotNull( response ); + assertTrue( response.getBody( ).jsonPath( ).getBoolean( "success" ) ); + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "/mappings" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + List resultList = response.getBody( ).jsonPath( ).getList( "", GroupMapping.class ); + assertEquals( 4, response.getBody( ).jsonPath( ).getList( "" ).size() ); + Optional found = resultList.stream( ).filter( map -> map.getGroupName( ).equals( "ldap group" ) && map.getRoles( ).size( ) == 2 && map.getRoles( ).contains( "role1" ) ).findAny( ); + assertTrue( found.isPresent( ) ); + } finally { + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .delete( "/mappings/ldap group" ) + .then( ) + .statusCode( 200 ); + } + } + + @Test + void deleteGroupMapping() { + String token = getAdminToken( ); + try + { + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .delete( "/mappings/archiva-admin" ) + .then( ) + .statusCode( 200 ).extract( ).response( ); + assertTrue( response.getBody( ).jsonPath( ).getBoolean( "success" ) ); + } finally { + // Put it back + Map jsonAsMap = new HashMap<>( ); + jsonAsMap.put( "groupName", "archiva-admin" ); + jsonAsMap.put( "roles", Arrays.asList( "System Administrator" ) ); + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .body( jsonAsMap ) + .when( ) + .post( "/mappings" ) + .then( ).statusCode( 201 ); + } + } + + @Test + void updateGroupMapping() { + String token = getAdminToken( ); + try + { + List list = Arrays.asList( "System Administrator", "role1", "role2", "role3" ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body(list) + .put( "/mappings/archiva-admin" ) + .then( ) + .statusCode( 200 ).extract( ).response( ); + assertTrue( response.getBody( ).jsonPath( ).getBoolean( "success" ) ); + } finally { + // Put it back + List list = Arrays.asList( "System Administrator" ); + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .body( list ) + .when( ) + .put( "/mappings/archiva-admin" ) + .then( ).statusCode( 200 ); + } + } + + @Test + void updateAndGetGroupMapping() { + String token = getAdminToken( ); + try + { + // The default implementation of redback uses the value from the configuration persistently + // and adds the updates to the configuration. + List list = Arrays.asList( "role1", "role2", "role3" ); + Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .body(list) + .put( "/mappings/archiva-admin" ) + .then( ) + .statusCode( 200 ).extract( ).response( ); + assertTrue( response.getBody( ).jsonPath( ).getBoolean( "success" ) ); + + response = given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .when( ) + .get( "/mappings" ) + .then( ).statusCode( 200 ).extract( ).response( ); + assertNotNull( response ); + List resultList = response.getBody( ).jsonPath( ).getList( "", GroupMapping.class ); + assertEquals( 3, response.getBody( ).jsonPath( ).getList( "" ).size() ); + for (GroupMapping mapping : resultList) { + System.out.println( mapping.getGroupName( ) + "/" + mapping.getUniqueGroupName( ) ); + for (String role : mapping.getRoles( )) { + System.out.println( "Role " + role ); + } + } + Optional found = resultList.stream( ).filter( map -> map.getGroupName( ).equals( "archiva-admin" ) && map.getRoles( ).size( ) == 4 && map.getRoles( ).contains( "role3" ) ).findAny( ); + assertTrue( found.isPresent( ) ); + + } finally { + // Put it back + List list = Arrays.asList( "System Administrator" ); + given( ).spec( getRequestSpec( token ) ).contentType( JSON ) + .body( list ) + .when( ) + .put( "/mappings/archiva-admin" ) + .then( ).statusCode( 200 ); + } + } + }