Skip to content

Commit

Permalink
Merge pull request #2766 from Micheleboychuk/DS-4495_HAL_link
Browse files Browse the repository at this point in the history
DS-4495 Restricted endpoints are sometimes the only HAL link path to public endpoints
  • Loading branch information
tdonohue committed Jun 4, 2020
2 parents 3fc20eb + 746fa4f commit 3a1522c
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 5 deletions.
Expand Up @@ -8,19 +8,24 @@
package org.dspace.app.rest.repository;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import org.dspace.app.rest.DiscoverableEndpointsService;
import org.dspace.app.rest.model.AuthorityRest;
import org.dspace.app.rest.model.AuthorizationRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.utils.AuthorityUtils;
import org.dspace.content.authority.ChoiceAuthority;
import org.dspace.content.authority.service.ChoiceAuthorityService;
import org.dspace.core.Context;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.hateoas.Link;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;

Expand All @@ -30,14 +35,18 @@
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
*/
@Component(AuthorityRest.CATEGORY + "." + AuthorityRest.NAME)
public class AuthorityRestRepository extends DSpaceRestRepository<AuthorityRest, String> {
public class AuthorityRestRepository extends DSpaceRestRepository<AuthorityRest, String>
implements InitializingBean {

@Autowired
private ChoiceAuthorityService cas;

@Autowired
private AuthorityUtils authorityUtils;

@Autowired
DiscoverableEndpointsService discoverableEndpointsService;

@PreAuthorize("hasAuthority('AUTHENTICATED')")
@Override
public AuthorityRest findOne(Context context, String name) {
Expand All @@ -63,4 +72,11 @@ public Page<AuthorityRest> findAll(Context context, Pageable pageable) {
public Class<AuthorityRest> getDomainClass() {
return AuthorityRest.class;
}

@Override
public void afterPropertiesSet() throws Exception {
discoverableEndpointsService.register(this, Arrays.asList(
new Link("/api/" + AuthorizationRest.CATEGORY + "/" + AuthorizationRest.NAME + "/search",
AuthorizationRest.NAME + "-search")));
}
}
Expand Up @@ -9,13 +9,15 @@

import java.io.IOException;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.dspace.app.rest.DiscoverableEndpointsService;
import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod;
import org.dspace.app.rest.exception.RESTAuthorizationException;
Expand All @@ -42,10 +44,12 @@
import org.dspace.xmlworkflow.storedcomponents.ClaimedTask;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.hateoas.Link;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;

Expand All @@ -56,7 +60,8 @@
*/

@Component(PoolTaskRest.CATEGORY + "." + ClaimedTaskRest.NAME)
public class ClaimedTaskRestRepository extends DSpaceRestRepository<ClaimedTaskRest, Integer> {
public class ClaimedTaskRestRepository extends DSpaceRestRepository<ClaimedTaskRest, Integer>
implements InitializingBean {

private static final Logger log = Logger.getLogger(ClaimedTaskRestRepository.class);

Expand All @@ -78,6 +83,9 @@ public class ClaimedTaskRestRepository extends DSpaceRestRepository<ClaimedTaskR
@Autowired
AuthorizeService authorizeService;

@Autowired
DiscoverableEndpointsService discoverableEndpointsService;

@Override
@PreAuthorize("hasPermission(#id, 'CLAIMEDTASK', 'READ')")
public ClaimedTaskRest findOne(Context context, Integer id) {
Expand Down Expand Up @@ -188,4 +196,11 @@ protected void delete(Context context, Integer id) {
public Page<ClaimedTaskRest> findAll(Context context, Pageable pageable) {
throw new RepositoryMethodNotImplementedException(ClaimedTaskRest.NAME, "findAll");
}

@Override
public void afterPropertiesSet() throws Exception {
discoverableEndpointsService.register(this, Arrays.asList(
new Link("/api/" + ClaimedTaskRest.CATEGORY + "/" + ClaimedTaskRest.NAME + "/search",
ClaimedTaskRest.NAME + "-search")));
}
}
Expand Up @@ -9,12 +9,14 @@

import java.io.IOException;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.DiscoverableEndpointsService;
import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod;
import org.dspace.app.rest.exception.UnprocessableEntityException;
Expand All @@ -25,9 +27,11 @@
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.service.EPersonService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.hateoas.Link;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;

Expand All @@ -39,11 +43,15 @@
*/

@Component(EPersonRest.CATEGORY + "." + EPersonRest.NAME)
public class EPersonRestRepository extends DSpaceObjectRestRepository<EPerson, EPersonRest> {
public class EPersonRestRepository extends DSpaceObjectRestRepository<EPerson, EPersonRest>
implements InitializingBean {

@Autowired
AuthorizeService authorizeService;

@Autowired
DiscoverableEndpointsService discoverableEndpointsService;

private final EPersonService es;


Expand Down Expand Up @@ -195,4 +203,10 @@ protected void delete(Context context, UUID id) throws AuthorizeException {
public Class<EPersonRest> getDomainClass() {
return EPersonRest.class;
}

@Override
public void afterPropertiesSet() throws Exception {
discoverableEndpointsService.register(this, Arrays.asList(
new Link("/api/" + EPersonRest.CATEGORY + "/registrations", EPersonRest.NAME + "-registration")));
}
}
Expand Up @@ -9,12 +9,14 @@

import java.io.IOException;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.dspace.app.rest.DiscoverableEndpointsService;
import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod;
import org.dspace.app.rest.exception.RESTAuthorizationException;
Expand All @@ -36,10 +38,12 @@
import org.dspace.xmlworkflow.state.actions.WorkflowActionConfig;
import org.dspace.xmlworkflow.storedcomponents.PoolTask;
import org.dspace.xmlworkflow.storedcomponents.service.PoolTaskService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.hateoas.Link;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;

Expand All @@ -50,7 +54,8 @@
*/

@Component(PoolTaskRest.CATEGORY + "." + PoolTaskRest.NAME)
public class PoolTaskRestRepository extends DSpaceRestRepository<PoolTaskRest, Integer> {
public class PoolTaskRestRepository extends DSpaceRestRepository<PoolTaskRest, Integer>
implements InitializingBean {

private static final Logger log = Logger.getLogger(PoolTaskRestRepository.class);

Expand All @@ -72,6 +77,9 @@ public class PoolTaskRestRepository extends DSpaceRestRepository<PoolTaskRest, I
@Autowired
AuthorizeService authorizeService;

@Autowired
DiscoverableEndpointsService discoverableEndpointsService;

@Override
@PreAuthorize("hasPermission(#id, 'POOLTASK', 'READ')")
public PoolTaskRest findOne(Context context, Integer id) {
Expand Down Expand Up @@ -146,4 +154,11 @@ protected PoolTaskRest action(Context context, HttpServletRequest request, Integ
public Page<PoolTaskRest> findAll(Context context, Pageable pageable) {
throw new RuntimeException("Method not allowed!");
}

@Override
public void afterPropertiesSet() throws Exception {
discoverableEndpointsService.register(this, Arrays.asList(
new Link("/api/" + PoolTaskRest.CATEGORY + "/" + PoolTaskRest.NAME + "/search",
PoolTaskRest.NAME + "-search")));
}
}
Expand Up @@ -9,11 +9,13 @@

import java.io.IOException;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.dspace.app.rest.DiscoverableEndpointsService;
import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod;
import org.dspace.app.rest.exception.MissingParameterException;
Expand All @@ -35,10 +37,12 @@
import org.dspace.eperson.Group;
import org.dspace.eperson.service.EPersonService;
import org.dspace.eperson.service.GroupService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.hateoas.Link;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;

Expand All @@ -48,7 +52,8 @@
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
*/
@Component(ResourcePolicyRest.CATEGORY + "." + ResourcePolicyRest.NAME)
public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourcePolicyRest, Integer> {
public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourcePolicyRest, Integer>
implements InitializingBean {

@Autowired
ResourcePolicyService resourcePolicyService;
Expand All @@ -68,6 +73,9 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourceP
@Autowired
ResourcePatch<ResourcePolicy> resourcePatch;

@Autowired
DiscoverableEndpointsService discoverableEndpointsService;

@Override
@PreAuthorize("hasPermission(#id, 'resourcepolicy', 'READ')")
public ResourcePolicyRest findOne(Context context, Integer id) {
Expand Down Expand Up @@ -312,4 +320,11 @@ protected void patch(Context context, HttpServletRequest request, String apiCate
resourcePatch.patch(obtainContext(), resourcePolicy, patch.getOperations());
resourcePolicyService.update(context, resourcePolicy);
}

@Override
public void afterPropertiesSet() throws Exception {
discoverableEndpointsService.register(this, Arrays.asList(
new Link("/api/" + ResourcePolicyRest.CATEGORY + "/" + ResourcePolicyRest.NAME + "/search",
ResourcePolicyRest.NAME + "-search")));
}
}
Expand Up @@ -7,6 +7,8 @@
*/
package org.dspace.app.rest;

import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
import static org.hamcrest.Matchers.is;
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;
Expand Down Expand Up @@ -195,6 +197,19 @@ public void retrieveCommonTypesWithSpaceValueTest() throws Exception {
.andExpect(jsonPath("$.page.totalElements", Matchers.is(1)));
}

@Test
public void discoverableNestedLinkTest() throws Exception {
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(get("/api"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._links",Matchers.allOf(
hasJsonPath("$.authorizations.href",
is("http://localhost/api/authz/authorizations")),
hasJsonPath("$.authorization-search.href",
is("http://localhost/api/authz/authorization/search"))
)));
}

@Test
public void retrieveSolrValueTest() throws Exception {
String token = getAuthToken(admin.getEmail(), password);
Expand Down
Expand Up @@ -1786,4 +1786,18 @@ public void getDirectEpersonGroups() throws Exception {
);

}

@Test
public void discoverableNestedLinkTest() throws Exception {
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(get("/api"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._links",Matchers.allOf(
hasJsonPath("$.epersons.href",
is("http://localhost/api/eperson/epersons")),
hasJsonPath("$.eperson-registration.href",
is("http://localhost/api/eperson/registrations"))
)));
}

}
Expand Up @@ -2407,4 +2407,17 @@ public void patchWithMultipleOperationsFailTest() throws Exception {
hasJsonPath("$.endDate", is(formatDate.format(endDate))),
hasJsonPath("$.description", nullValue()))));
}

@Test
public void discoverableNestedLinkTest() throws Exception {
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(get("/api"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._links",Matchers.allOf(
hasJsonPath("$.resourcepolicies.href",
is("http://localhost/api/authz/resourcepolicies")),
hasJsonPath("$.resourcepolicy-search.href",
is("http://localhost/api/authz/resourcepolicy/search"))
)));
}
}
Expand Up @@ -1800,4 +1800,21 @@ public void stepEmbedTest() throws Exception {
"Workflow Item 3", "2016-02-13")))
.andExpect(jsonPath("$._embedded.step", WorkflowStepMatcher.matchWorkflowStepEntry(step)));
}

@Test
public void discoverableNestedLinkTest() throws Exception {
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(get("/api"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._links",Matchers.allOf(
hasJsonPath("$.claimedtasks.href",
is("http://localhost/api/workflow/claimedtasks")),
hasJsonPath("$.claimedtask-search.href",
is("http://localhost/api/workflow/claimedtask/search")),
hasJsonPath("$.pooltasks.href",
is("http://localhost/api/workflow/pooltasks")),
hasJsonPath("$.pooltask-search.href",
is("http://localhost/api/workflow/pooltask/search"))
)));
}
}

0 comments on commit 3a1522c

Please sign in to comment.