Skip to content

Commit

Permalink
SHIBUI-2646: MDQ fixes for trailing slashes
Browse files Browse the repository at this point in the history
  • Loading branch information
chasegawa committed Jan 7, 2025
1 parent 400d871 commit 6d54702
Show file tree
Hide file tree
Showing 4 changed files with 3 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class EntitiesController {
@Autowired
private EntityDescriptorRepository entityDescriptorRepository;

@RequestMapping(value = "/entities", produces = "application/xml")
@RequestMapping(value = {"/entities", "/entities/"}, produces = {"application/xml", "application/xml"})
@Operation(description = "Endpoint based on the MDQ spec to return all entity's information. see: https://spaces.at.internet2.edu/display/MDQ/Metadata+Query+Protocol",
summary = "Return all the entities from the entity's id", method = "GET")
@Transactional(readOnly = true)
Expand All @@ -72,28 +72,13 @@ public ResponseEntity<?> getAllXml() throws MarshallingException, ResolverExcept
return new ResponseEntity<>("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + xmlDeclarationClean, new HttpHeaders(), HttpStatus.OK);
}

@RequestMapping(value = "/entities/{entityId:.*}")
@Operation(description = "Endpoint based on the MDQ spec to return a single entity's information. see: https://spaces.at.internet2.edu/display/MDQ/Metadata+Query+Protocol",
summary = "Return a single entity from the entity's id", method = "GET")
@Transactional(readOnly = true)
public ResponseEntity<?> getOne(final @PathVariable String entityId, HttpServletRequest request) throws UnsupportedEncodingException, ResolverException {
EntityDescriptor entityDescriptor = this.getEntityDescriptor(entityId);
if (entityDescriptor == null) {
return ResponseEntity.notFound().build();
}
EntityDescriptorRepresentation entityDescriptorRepresentation = entityDescriptorService.createRepresentationFromDescriptor(entityDescriptor);
HttpHeaders headers = new HttpHeaders();
headers.set("Last-Modified", formatModifiedDate(entityDescriptorRepresentation));
return new ResponseEntity<>(entityDescriptorRepresentation, headers, HttpStatus.OK);
}

private String formatModifiedDate(EntityDescriptorRepresentation entityDescriptorRepresentation) {
Instant instant = entityDescriptorRepresentation.getModifiedDateAsDate().toInstant(ZoneOffset.UTC);
Date date = Date.from(instant);
return DateUtils.formatDate(date, DateUtils.PATTERN_RFC1123);
}

@RequestMapping(value = "/entities/{entityId:.*}", produces = "application/xml")
@RequestMapping(value = {"/entities/{entityId:.*}", "/entities/{entityId:.*}/"}, produces = {"application/xml", "application/xml"})
@Operation(description = "Endpoint based on the MDQ spec to return a single entity's information. see: https://spaces.at.internet2.edu/display/MDQ/Metadata+Query+Protocol",
summary = "Return a single entity from the entity's id", method = "GET")
@Transactional(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,50 +99,6 @@ class EntitiesControllerIntegrationTests extends AbstractBaseDataJpaTest {
}
}

@WithMockAdmin
def 'GET /entities/{resourceId} existing'() {
given:
def entityDescriptorOne = new EntityDescriptor(resourceId: 'uuid-1', entityID: 'eid1', serviceProviderName: 'sp1', serviceEnabled: true, idOfOwner: "admingroup")
entityDescriptorRepository.save(entityDescriptorOne)
entityManager.flush()
entityManager.clear()

when:
def result = mockMvc.perform(get("/entities/eid1"))

then:
result.andExpect(status().isOk())
.andExpect(jsonPath("\$.entityId").value("eid1"))
.andExpect(jsonPath("\$.serviceProviderName").value("sp1"))
.andExpect(jsonPath("\$.serviceEnabled").value(true))
.andExpect(jsonPath("\$.idOfOwner").value("admingroup"))
}

@WithMockUser(value = "someUser", roles = ["USER"])
def 'GET /entities/{resourceId} existing, validate group access'() {
given:
Group g = userService.getCurrentUserGroup()

def entityDescriptorOne = new EntityDescriptor(resourceId: 'uuid-1', entityID: 'eid1', serviceProviderName: 'sp1', serviceEnabled: true, idOfOwner: "someUser")
def entityDescriptorTwo = new EntityDescriptor(resourceId: 'uuid-2', entityID: 'eid2', serviceProviderName: 'sp2', serviceEnabled: false, idOfOwner: Group.ADMIN_GROUP.getOwnerId())

entityDescriptorRepository.saveAndFlush(entityDescriptorOne)
entityDescriptorRepository.saveAndFlush(entityDescriptorTwo)

ownershipRepository.saveAndFlush(new Ownership(g, entityDescriptorOne))
ownershipRepository.saveAndFlush(new Ownership(Group.ADMIN_GROUP, entityDescriptorTwo))

when:
def result = mockMvc.perform(get("/entities/eid1"))

then:
result.andExpect(status().isOk())
.andExpect(jsonPath("\$.entityId").value("eid1"))
.andExpect(jsonPath("\$.serviceProviderName").value("sp1"))
.andExpect(jsonPath("\$.serviceEnabled").value(true))
.andExpect(jsonPath("\$.idOfOwner").value("someUser"))
}

@WithMockUser(value = "someUser", roles = ["USER"])
def 'GET /entities/{resourceId} existing, owned by some other user'() {
when:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,40 +94,6 @@ class EntitiesControllerTests extends AbstractBaseDataJpaTest {
result.andExpect(status().isNotFound())
}

def 'GET /api/entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1'() {
when:
def result = mockMvc.perform(get('/entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1'))

then:
// Response headers section 2.5
// from the spec https://www.ietf.org/archive/id/draft-young-md-query-14.txt
result.andExpect(status().isOk())
.andExpect(header().exists(HttpHeaders.CONTENT_TYPE)) // MUST HAVE
// .andExpect(header().exists(HttpHeaders.CONTENT_LENGTH)) // SHOULD HAVE - should end up from etag filter, so skipped for test
// .andExpect(header().exists(HttpHeaders.CACHE_CONTROL)) // SHOULD HAVE - should be included by Spring Security
// .andExpect(header().exists(HttpHeaders.ETAG)) // MUST HAVE - is done by filter, so skipped for test
.andExpect(header().exists(HttpHeaders.LAST_MODIFIED))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath('$.entityId', is("http://test.scaldingspoon.org/test1")))
}

def 'GET /entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1'() {
when:
def result = mockMvc.perform(get('/entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1'))

then:
// Response headers section 2.5
// from the spec https://www.ietf.org/archive/id/draft-young-md-query-14.txt
result.andExpect(status().isOk())
.andExpect(header().exists(HttpHeaders.CONTENT_TYPE)) // MUST HAVE
// .andExpect(header().exists(HttpHeaders.CONTENT_LENGTH)) // SHOULD HAVE - should end up from etag filter, so skipped for test
// .andExpect(header().exists(HttpHeaders.CACHE_CONTROL)) // SHOULD HAVE - should be included by Spring Security
// .andExpect(header().exists(HttpHeaders.ETAG)) // MUST HAVE - is done by filter, so skipped for test
.andExpect(header().exists(HttpHeaders.LAST_MODIFIED))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath('$.entityId').value("http://test.scaldingspoon.org/test1"))
}

def 'GET /api/entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1 XML'() {
given:
def expectedBody = '''<?xml version="1.0" encoding="UTF-8"?>
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name=shibui
group=edu.internet2.tier.shibboleth.admin.ui
version=2.0.5
version=2.0.6-SNAPSHOT

### library versions ###
## As of 2-23-23
Expand Down

0 comments on commit 6d54702

Please sign in to comment.