[Task 70131] added support for the login as feature and added simple test

This commit is contained in:
Raf Ponsaerts
2020-03-31 15:55:36 +02:00
parent 2334a87e3a
commit 4698ebcdbc
2 changed files with 95 additions and 0 deletions

View File

@@ -8,18 +8,27 @@
package org.dspace.app.rest.security;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.authorize.factory.AuthorizeServiceFactory;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.factory.EPersonServiceFactory;
import org.dspace.eperson.service.EPersonService;
import org.dspace.services.RequestService;
import org.dspace.util.UUIDUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
@@ -37,12 +46,19 @@ public class StatelessAuthenticationFilter extends BasicAuthenticationFilter {
private static final Logger log = LoggerFactory.getLogger(StatelessAuthenticationFilter.class);
private static final String ON_BEHALF_OF_REQUEST_PARAM = "X-On-Behalf-Of";
private static final String ADMIN = "ADMIN";
private RestAuthenticationService restAuthenticationService;
private EPersonRestAuthenticationProvider authenticationProvider;
private RequestService requestService;
private AuthorizeService authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService();
private EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
public StatelessAuthenticationFilter(AuthenticationManager authenticationManager,
RestAuthenticationService restAuthenticationService,
EPersonRestAuthenticationProvider authenticationProvider,
@@ -81,6 +97,10 @@ public class StatelessAuthenticationFilter extends BasicAuthenticationFilter {
//Get the Spring authorities for this eperson
List<GrantedAuthority> authorities = authenticationProvider.getGrantedAuthorities(context, eperson);
String onBehalfOfParameterValue = request.getHeader(ON_BEHALF_OF_REQUEST_PARAM);
if (onBehalfOfParameterValue != null) {
return getOnBehalfOfAuthentication(context, onBehalfOfParameterValue);
}
//Return the Spring authentication object
return new DSpaceAuthentication(eperson.getEmail(), authorities);
@@ -92,4 +112,33 @@ public class StatelessAuthenticationFilter extends BasicAuthenticationFilter {
return null;
}
private Authentication getOnBehalfOfAuthentication(Context context, String onBehalfOfParameterValue) {
UUID epersonUuid = UUIDUtils.fromString(onBehalfOfParameterValue);
if (epersonUuid == null) {
throw new DSpaceBadRequestException("The parameter value of " + ON_BEHALF_OF_REQUEST_PARAM +
" was not a proper UUID");
}
try {
EPerson onBehalfOfEPerson = ePersonService.find(context, epersonUuid);
if (onBehalfOfEPerson == null) {
throw new DSpaceBadRequestException("The parameter value of " + ON_BEHALF_OF_REQUEST_PARAM +
" was not a proper EPerson UUID");
}
if (authorizeService.isAdmin(context)) {
requestService.setCurrentUserId(epersonUuid);
context.switchContextUser(onBehalfOfEPerson);
return new DSpaceAuthentication(onBehalfOfEPerson.getEmail(),
authenticationProvider.getGrantedAuthorities(context,
onBehalfOfEPerson));
} else {
throw new AccessDeniedException("The current EPerson was not an admin and " +
"cannot use the on behalf of functionality");
}
} catch (SQLException e) {
log.error(e.getMessage(), e);
return null;
}
}
}

View File

@@ -0,0 +1,46 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.dspace.app.rest.matcher.EPersonMatcher;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.junit.Test;
public class LoginAsEPersonIT extends AbstractControllerIntegrationTest {
@Test
public void loggedInUserRetrievalTest() throws Exception {
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/authn/status")
.param("projection", "full"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.eperson", EPersonMatcher.matchEPersonOnEmail(admin.getEmail())));
}
@Test
public void loggedInAsOtherUserRetrievalTest() throws Exception {
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/authn/status")
.param("projection", "full")
.header("X-On-Behalf-Of", eperson.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.eperson",
EPersonMatcher.matchEPersonOnEmail(eperson.getEmail())));
}
}